
Remote:遠端倉庫 Repository:本地倉庫
Workspace: 工作區 Index: 暫存區
安裝Git
Windows
在官網
下載下傳安裝程式, 然後按預設選項安裝即可。
安裝完成後,在開始菜單裡找到“Git”->“Git Bash”,蹦出一個類似指令行視窗的東西,就說明Git安裝成功!
Linux
系統版本:CentOS 7.3,x86_64 , root使用者
檢視系統是否已安裝git :
git --version
, 如果提示
bash: /usr/bin/git: No such file or directory
,則說明系統中還沒有安裝git; 如果顯示了git 版本号,則證明系統中已經安裝了git。
Redhat系的Linux發行版,安裝git最便捷的方法是直接使用yum 安裝:
yum install git
, 但是經過測試,CentOS 7.3 通過yum 安裝的Git 版本預設為v1.8.3 , 而目前git最新版本為v2.16.0,低版本的git存在安全漏洞,是以不建議使用yum安裝,推薦使用源碼安裝git.
- 解除安裝已經安裝的低版本的git:
yum remove git
- 安裝git依賴包
sudo yum groupinstall "Development Tools"
sudo yum install -y curl-devel expat-devel gettext-devel openssl-devel perl-CPAN perl-devel zlib-devel
- 依賴包安裝完成後,需要找出并 下載下傳最新版本的git ,,位于清單頂部的是最新版本,注意不要選擇帶有-rc的版本,因為它代表了一個候選釋出版本。 選擇最新的版本 ,使用wget下載下傳:
Git學習筆記
wget https://github.com/git/git/archive/v2.15.1.tar.gz
- 安裝git
#解壓
tar -zxvf git.tar.gz
#編譯
cd git* #進入git解壓目錄
make configure
./configure --prefix=/usr/local/
make prefix=/usr/local/ all
make install
- 檢視版本
, 如果顯示的git版本還是v1.8或提示找不到git目錄,執行指令:git --version
,就可以了。cp /usr/local/bin/git* /usr/bin/
Git學習筆記
設定Git
設定你的一些個人資訊,如你送出的姓名和電子郵件:
$ git config --global user.name 'shijianzhihu'
$ git config --global user.email '[email protected]'
#檢視所有已配置的全局資訊
$ git config --list
Git 常用指令
以下所有的指令說明都基于Git v2.13.0,不同版本的Git ,指令可能會有所差別!
$ git --version #檢視git 版本
$ git [command] --help #檢視command使用者手冊
git clone
git clone
用來從從遠端主機克隆一個版本庫,文法為:
git clone <版本庫位址>
,該指令會在本地主機生成一個與遠端主機版本庫同名的目錄,如果要指定不同的目錄名,可以将目錄名作為
git clone
指令的第二個參數:
git clone <版本庫的網址> <本地目錄名>
git remote
Git要求每個遠端主機都必須指定一個主機名。
git remote
指令就用于管理主機名.
#檢視所有遠端主機名
$ git remote
origin
#檢視遠端主機位址
$ git remote -v
origin https://github.com/naver/ngrinder.git (fetch)
origin https://github.com/naver/ngrinder.git (push)
git fetch
一旦遠端主機的版本庫有了更新,需要将這些更新取回本地,這時就要用到
git fetch
指令.
#将遠端主機的所有分支的更新取回本地
$ git fetch <遠端主機名>
如:git fetch origin
#取回指定分支的更新
$ git fetch <遠端主機名> <分支名>
如:git fetch origin dev
git branch
git branch
用來顯示、建立或删除分支。
OPTIONS
# 不帶參數時,會列出所有本地分支,并且在目前分支前加"*";
$ git branch
dev
master
* test
<newBranch>
#建立本地分支,但不會自動切換到該分支
$ git branch bug-fixed
<-r, --remotes>
#列出所有遠端分支
$ git branch -r
origin/bug-fixed
origin/b2b
origin/beta
origin/collections
origin/chart
<-a --all>
#列出所有本地分支和遠端分支
$ git branch -a
<-m ,--move | -M>
#移動/重命名一個分支和相應的曆史資訊
#<-M>:強制move/rename
$ git branch -m bug-fixed bug-fixed2
<-d, --delete | -D>
#删除本地分支,不能删除目前checkout的分支;
#如果要删除的分支有未合并的内容,則會報錯:'the branch XXX is not fully merged',解決辦法:使用'-D' 強制删除;
$ git branch -D 'bug-fixed'
#補充:利用shell管道指令實作批量删除分支
$ git branch | grep 'branchName' | xargs branch -D
<--set-upstream-to origin/branchname localBranchname>
注意,<–set-upstream-to> 在已經替代了 <–set-upstream>,二者跟随的參數需要對調一下位置;
#設定本地分支與遠端分支關聯,如果沒有關聯的情況下,git pull 會提示如下資訊:
$ git push origin test
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> test
設定遠端關聯分支的方法,如下
$ git branch --set-upstream-to origin/test test
Branch test set up to track remote branch test from origin.
$ git pull
Already up-to-date.
<-v, --verbose | -vv>
#<-v>:檢視本地分支最後的修改資訊,目前分支名稱前會帶有'*'
$ git branch -av
bug-fixed3 fdcbdf7 add bug -fixed2
dev 1599863 test
* master 9faecaf [ahead 1] update test.txt #[ahead 1]表示本地分支比遠端分支領先一個commit
test 1599863 test
remotes/origin/HEAD -> origin/master
remotes/origin/bug-fixed3 fdcbdf7 add bug -fixed2
#<-vv>:在git branch -v的基礎上,顯示本地分支的遠端關聯分支(upstream branch);
#檢視遠端關聯分支,可以使用git config --list指令
$ git branch -vv
bug-fixed3 fdcbdf7 add bug -fixed2
dev 1599863 test
* master 9faecaf [origin/master: ahead 1] update test.txt
test 1599863 test
git checkout
git checkout
用來切換分支或恢複工作樹檔案。
<branch>
#切換目前分支到本地已有分支
$ git checkout dev
Switched to branch 'dev'
#建立本地分支,并切換到該分支
$ git checkout -b five
Switched to a new branch 'five'
#建立本地分支,并切換到該分支,而且關聯遠端分支
$ git checkout -b six --track origin/dev
Switched to a new branch 'six'
Branch six set up to track remote branch dev from origin.
第三條指令相當于以下指令的合集:
$ git branch
$ git checkout six
$ git branch --set-upstream-to origin/dev six
<-- fileNmae> #'--' 和'fileName'之間有空格!
#将指定檔案在工作區的修改撤銷到最近一次git add 或git commit時的内容(隻對tracked file有效)
比如下面的兩個例子:
$ cat test.txt
one
$ git add . -v
add 'test.txt'
$ git commit -m 'update test.txt'
[test a2d987d] update test.txt
1 file changed, 1 insertion(+)
$ vim test.txt
$ cat test.txt
one
two
$ git checkout -- test.txt #注意空格,否則報錯
$ cat test.txt
one
$ git status
nothing to commit, working tree clean
****************************************
$ cat test.txt
one
two
$ vim test.txt
$ cat test.txt
one
two
three
$ vim test.txt
$ cat test.txt
one
two
three
four
$ git checkout -- test.txt
$ cat test.txt
one
two
補充:
$ git checkout -- stu.txt test.txt
$ git checkout -- *
$ git checkout -- *.txt
# git checkout -- 不加檔案名來檢視目前工作區修改了哪些檔案
$ git checkout --
M blog.txt
D start.txt
Your branch is up-to-date with 'origin/sprider'.
# 取檔案在commit_id時的版本
$ git checkout 1599863 fileName
git status
git status
用來顯示工作樹狀态, git會非常友好的提示使用者下一步的操作,請看下面的例子:
$ git status
On branch test
Your branch is up-to-date with 'origin/test'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
blog.txt
nothing added to commit but untracked files present (use "git add" to track)
$ git add blog.txt
$ git status
#
On branch test
Your branch is up-to-date with 'origin/test'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: blog.txt
$ git commit -m 'add blog.txt'
$ git status
On branch test
Your branch is ahead of 'origin/test' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
git add
git add
指令主要用于把我們要送出的檔案的資訊添加到索引庫(Index)中。當我們使用
git commit
時,git将依據索引庫中的内容來進行檔案的送出。
git add
指令可以在commit之前多次執行。
git add file
COMMON OPTIONS
<pathspec>
#可以使用'*'模糊比對路徑
$ git add *.c
# 路徑可以到目錄層級
$ git add test/
<-v,--verbose>
#顯示本次added的檔案名
$ git add -v file3.txt
add 'file3.txt'
$ git add -v study/
add 'study/study.txt'
<-f, --force>
#允許添加被忽略的檔案
#關于git忽略檔案的介紹,見下一小節
$ git add -f commonVars.pyc
<-u, --update>
#add被修改(modified)和被删除(deleted)檔案,不包含新檔案(new,untracked file)
$ git add -uv
<-A, --all>
#add所有變化,包括被修改(modified)、被删除(deleted)檔案和包括新檔案(new)
$ git add -Afv
git add -A | git add -u |git add .
-
.:他會監控工作區的狀态樹,使用它會把工作時的所有變化送出到暫存區,包括modified、new和deleted ;git add
-
:他僅監控已經被add的檔案(即tracked file),他會将被修改的檔案送出到暫存區。add -u 不會送出new(untracked file);git add -u
-
git add -A
:等同于 git add .;
注意,在Git v1.x.x版本,git add . 不能添加deleted檔案
git 特殊檔案
有些時候,我們必須或被必須把某些檔案放到Git的工作目錄中,但是又不能送出它們。這就導緻每次
git status
都會顯示Untracked files ... 。為了解決這個檔案,可以在Git工作區的根目錄下建立一個特殊的.gitignore檔案,這個檔案的作用就是告訴Git哪些檔案不需要添加到版本管理中。實際項目中,很多檔案都是不需要版本管理的,比如Python的.pyc檔案和一些包含密碼的配置檔案等等。這個檔案的内容是一些規則,Git會根據這些規則來判斷是否将檔案添加到版本控制中。
Git bash建立".gitignore" :
vim .gitignore
, GitHub中已經為我們準備了各種配置檔案,隻需要組合一下就可以使用了。所有配置檔案可以直接線上浏覽:
https://github.com/github/gitignore常用的規則有:
1. /mtk/ #過濾整個檔案夾
2. *.zip #過濾所有.zip檔案
3. /mtk/do.c #過濾某個具體檔案
忽略檔案的原則是:
- 忽略作業系統自動生成的檔案,比如縮略圖等;
- 忽略編譯生成的中間檔案、可執行檔案等,也就是如果一個檔案是通過另一個檔案自動生成的,那自動生成的檔案就沒必要放進版本庫,比如Java編譯産生的.class檔案;
- 忽略你自己的帶有敏感資訊的配置檔案,比如存放密碼的配置檔案。
git commit
git commit
記錄對存儲庫的更改資訊,此指令預設送出的是暫存區的内容,也就是 Changes to be committed 中的檔案,最常用的參數是<-m>,用來添加本次送出的相關資訊,如:git commit -m 'update file'
如果使用了<-a>參數,則除了将暫存區裡的檔案送出外,還送出 Changes but not updated 中的檔案。通常我們送出git的時候都是通過以下三大步:
git add .
git commit -m "some str"
git push
實際上,你隻需要兩條指令就夠了,除非有新的檔案(untracked file)要被添加進去。
git commit -am "some str"
git push
git pull
git pull指令的作用是,取回遠端主機指定分支的更新,再與本地的指定分支合并。實質上等同于先做git fetch,再做git merge.
#完整格式
$ git pull <遠端主機名> <遠端分支名>:<本地分支名>
#比如:取回origin主機的bugifx分支與本地的bugfix2分支合并,需要寫成下面這樣
git pull origin bugfix:bugfix2
#如果遠端分支是與目前分支合并,則本地分支名可以省略
$ git pull origin dev
#如果目前分支與遠端分支存在關聯關系,遠端分支名也可以省略
$ git pull origin
#如果目前分支隻有一個追蹤分支,則遠端主機名也可以省略
$ git pull
#上面指令表示為:目前分支自動與唯一一個追蹤分支進行合并
**********************************************************
#如果合并需要使用rebase模式,可以加上'-- rebase'選項
$ git pull --rebase <遠端主機名> <遠端分支名>:<本地分支名>
**********************************************************
#如果遠端主機删除了某個分支,預設情況下,git pull 不會在拉取遠端分支的時候,删除對應的本地分支。這是為了防止,由于其他人操作了遠端主機,導緻git pull不知不覺删除了本地分支。但是,你可以改變這個行為,加上參數 -p 就會在本地删除遠端已經删除的分支。
$ git pull -p
# 等同于下面的指令
$ git fetch --prune origin
$ git fetch -p
git:檢視追蹤分支
#這個資訊實際是存在config 檔案中的,可以用下面的指令來檢視xxx分支的資訊
$ git config -l |grep 'branch.xxx'
# git v2.15+版本,可以使用以下指令檢視追蹤分支資訊
$ git branch -vv
git:手動設定追蹤分支
#方法一
$ git branch --set-upsteam XXX origin/xxxx
#方法二
#删掉本地分支,然後重新建立此分支,并且指定其 track 資訊
$ git checkout -b XXX --track origin/xxxx
git push
git push
指令用于将本地分支的更新,推送到遠端主機。它的指令格式與git pull指令相仿但不要搞混了,其實很容易了解區分的.
#完整格式
$ git push <遠端主機名> <本地分支名>:<遠端分支名>
#如果省略遠端分支名,則表示将本地分支推送與之存在"追蹤關系"的遠端分支(通常兩者同名)
#如果該遠端分支不存在,則會被建立。
$ git push origin dev
#如果省略本地分支名,則表示删除指定的遠端分支,因為這表示推送一個空的本地分支到遠端分支。
$ git push origin :dev
#注意origin 和冒号之間需要有空格
#如果目前分支與遠端分支存在關聯關系,遠端分支名也可以省略
$ git push origin
如果目前分支與遠端分支沒有追蹤關系,則會報錯:
fatal: The current branch bug-fixed2 has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin bug-fixed2
#如果目前分支隻有一個追蹤分支,則遠端主機名也可以省略
$ git push
git log | git reflog
git log 用來檢視目前分支的送出曆史,不包含已經被撤銷的commit:
$ git log
commit 150089329868f665cfd6a1f1ac301d31ff232c75 (HEAD -> sprider)
Author: xxxxx <[email protected]>
Date: Tue Feb 6 14:14:06 2018 +0800
Revert "test"
This reverts commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459.
commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459
Author: xxxxx <[email protected]>
Date: Tue Feb 6 14:13:54 2018 +0800
test
如果嫌輸出資訊太多,以試試加上--oneline參數:
$ git log --oneline
1500893 (HEAD -> sprider) Revert "test"
5e2d6fc test
a0eb8b5 update blog.txt
ec9734c Revert "start test"
1616640 Revert "blog"
顯示每次送出的内容差異可以使用< -p> 參數,<-n>則為僅顯示最近的n次曆史:
$ git log -p -1
commit 150089329868f665cfd6a1f1ac301d31ff232c75 (HEAD -> sprider)
Author: xxxxx <[email protected]>
Date: Tue Feb 6 14:14:06 2018 +0800
Revert "test"
This reverts commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459.
diff --git a/blog b/blog
index 40a3b4a..9daeafb 100644
--- a/blog
+++ b/blog
@@ -1 +1 @@
-test111
+test
git reflog 用來顯示整個本地倉儲的commit, 包括所有branch的commit, 甚至包括已經撤銷的commit, 隻要HEAD發生了變化(如checkout branch, pull, commit等), 就會在reflog裡面看得到。
$ git reflog
1500893 (HEAD -> sprider) HEAD@{0}: checkout: moving from six to sprider
02cffe0 (six) HEAD@{1}: commit: branch six
1599863 (origin/dev, five) HEAD@{2}: checkout: moving from sprider to six
1500893 (HEAD -> sprider) HEAD@{3}: revert: Revert "test"
5e2d6fc HEAD@{4}: commit: test
git revert | git reset
git revert
用來復原一些現有的送出, 但并不是從項目曆史中移除這個commit,舊的commit還是保留在曆史項目裡面的,而git reset 則會删除舊的commit, 這樣做的好處是防止了項目丢失曆史。
用法:
git revert <commit-id>
$ git log --oneline | head -n 1
a0eb8b5 update blog.txt
$ git revert HEAD
[sprider 60d4654] Revert "update blog.txt"
1 file changed, 1 insertion(+), 2 deletions(-)
$ git log --oneline | head -n 2
60d4654 Revert "update blog.txt"
a0eb8b5 update blog.txt
git reset <--hard|soft|mixed|merge|keep> commit 也是常用的版本復原指令,其中比較重要的參數是mode,也就是 --hard、--soft、--mixed。。。比較常見的是--hard和--soft;
--hard是指完全重設,會把回退到某版本之後的修改全部删除,
--soft這是個回退解體,讓版本庫回退到某個版本,這個版本之後的修改全部存在緩存區,這個時候在commit的話,又會把會退的部分重新加載到最新版本中;
git diff
git diff
用于比較兩次修改之間的差異。
- 比較工作區與暫存區
git diff 不加參數即預設比較工作區與暫存區
$ git diff
diff --git a/b2.txt b/b2.txt
index be738a5..2ffe5d8 100644
--- a/b2.txt
+++ b/b2.txt
@@ -1,2 +1,2 @@
test1
-test222
+22dsada2
- 比較暫存區與最新本地版本庫
git diff --cached
- 比較工作區與最新本地版本庫
git diff HEAD
- 比較工作區與指定commit-id的差異
git diff commit-id
- 比較暫存區與指定commit-id的差異
git diff --cached commit-id
- 比較兩個commit-id之間的差異
git diff commit-id commit-id
git stash
git stash 用來備份目前的工作區的内容,從最近的一次送出中讀取相關内容,讓工作區保證和上次送出的内容一緻。同時,将目前的工作區内容儲存到Git棧中。
git stash list 顯示Git棧内的所有備份,可以利用這個清單來決定從那個地方恢複。
git stash clear 清空Git棧.
git stash pop 從Git棧中讀取最近一次stash的内容,恢複工作區的相關内容。
兩種恢複方法:
- 用git stash apply恢複,但是恢複後,stash内容并不删除,你需要用git stash drop來删除;
- 用git stash pop,恢複的同時把stash内容也删了;
可以多次stash,恢複的時候,先用git stash list檢視,然後恢複指定的stash,用指令:
git stash apply stash@{0}
git rm
git rm
用于從從工作樹和暫存區中删除檔案,他作用的對象隻能是tracked files .
它的作用和
git add
類似,可以了解為一個是添加一個是修改。
git rm
要和
git commit
配合使用,才真正能起到删除的作用。
$ git rm test.txt stu.txt
rm 'stu.txt'
rm 'test.txt'
$ git status
On branch test
Your branch is up-to-date with 'origin/test'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: stu.txt
deleted: test.txt
$ git commit -m 'delete two files'
[test ccd7143] delete two files
2 files changed, 4 deletions(-)
delete mode 100644 stu.txt
delete mode 100644 test.txt
$ git status
On branch test
Your branch is ahead of 'origin/test' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
#删除檔案夾,-r表示遞歸删除,-f表示強制删除
$ git rm -rf qt/
rm 'qt/file.txt'
$ git rm -f rainbow.txt #不能對untracked file使用
fatal: pathspec 'rainbow.txt' did not match any files
git rm 和 rm 的差別
通過上面簡單的介紹,我們發現
git rm
和 shell 指令
rm
非常相似,我們是否可以不使用
git rm
,而是直接
rm
後,然後再
git add/commit
,這樣是否可以呢? 答案當然是可以的。
使用
git rm
來删除檔案,git同時會将操作月曆記錄下來,
git log
就可以看到;而使用
rm
來删除檔案,git并不會記錄,這也是十分易于了解的。直覺的來講,
git rm
删除過的檔案,執行
git commit -m "abc"
送出時,會自動将删除該檔案的操作送出上去;而對于用
rm
指令直接删除的檔案,執行
git commit -m "abc"
送出時,則不會将删除該檔案的操作送出上去。不過不要緊,即使你已經通過 rm 将某個檔案删除掉了,也可以再通過
git rm
指令重新将該檔案從 git 的記錄中删除掉,這樣的話,在執行
git commit -am "abc"
後,也能将這個删除操作送出上去。(
git commit -am
寫成
git commit -ma
會報錯)
一般說來,在git目錄下删除檔案時,可以選擇以下兩種方式:
- git rm + git commit -m 'text'
- rm + git commit -am 'text'
git mv
git mv
用來移動或重命名檔案、目錄或符号連結。
$ git mv b1.txt b2.txt
$ git mv rainbow.txt sprider/
$ git status
On branch sprider
Your branch is ahead of 'origin/sprider' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: b1.txt -> b2.txt
renamed: rainbow.txt -> sprider/rainbow.txt
$ git commit -m 'rename and move'
[sprider b08e44d] rename and move
2 files changed, 0 insertions(+), 0 deletions(-)
rename b1.txt => b2.txt (100%)
rename rainbow.txt => sprider/rainbow.txt (100%)
參考文檔
- Git 教程 ,廖雪峰
- Git遠端操作詳解 ,阮一峰
- Git忽略規則.gitignore梳理 ,散盡浮華
- git的reset和checkout的差別 ,chanjarster
- git add -A 和 git add . 的差別 ,PajamaCat
- git branch用法總結 ,KKK_Kevin
- Git自學之路(四) - gitbranch 分支 ,JunkChen-程開均
- Git中的upstream和downstream概述 ,易生一世
- “git rm” 和“rm”的差別 ,jfkidear
- git commit -m與git commit -am的差別
- Git的撤消操作 - 重置, 簽出 和 撤消