一、概念
1、工作區:working directory工作目錄
2、暫存區:index(stage), 只有被增加到暫存區的修改纔會被提交到版本庫
3、版本庫:倉庫(repository),修改要先添加到暫存區才能被提交
4、 HEAD:指向最後一次提交的結果
二、使用
1、創建版本庫
#git init
2、把文件提交到倉庫
第一步:將文件增加到暫存區
#git add file
第二步:將文件提交到倉庫
#git commit -m “log info”
3、查看倉庫狀態
#git status
4、查看文件具體修改內容
#git diff file
5、版本回退
(1)回退到上一個版本: #git reset --hard HEAD^
(2)回退到上上個版本: #git reset --hard HEAD^^
(3)回退到前第n個版本: #git reset --hard HEAD~n
(4)回退到指定版本(根據版本號commit ID):#git reset --hard “commit ID”
6、查看版本日誌(內含版本號)
#git log
7、查看歷史版本號(歷史命令)
#git reflog
8、撤銷修改
【場景一】:修改了工作區某文件內容,還未增加到暫存區
#git checkout -- file
注:撤銷工作區的所有修改,即用版本庫的版本替換工作區的版本。
這裏有兩種情況:
一種是file自修改後還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是file已經添加到暫存區後,又作了修改,現在,撤銷修改就回到添加到暫存區後的狀態。
總之,就是讓這個文件回到最近一次git commit或git add時的狀態。
【場景二】:修改增加到了暫存區,這時分兩步撤銷修改
第一步:從暫存區修改撤回工作區, 這時回到場景一
#git reset HEAD file
第二步:同場景一一樣,撤銷工作區修改
#git checkout -- file
【場景三】:修改已經被提交到版本庫(未推送到遠程庫),這時就只能版本回退了
#git reset --hard HEAD^
9、文件刪除(已提交給版本庫)
場景:你把工作區的一個文件刪除了(#rm file),現在有兩種情況:
第一、確實要從版本庫刪除該文件,那就用git rm將文件從版本庫刪掉,並用commit提交修改(刪除)操作(因爲這也相當於一次修改)。
#git rm file
#git commit -m “remove file”
第二、誤刪了文件,想要恢復,因爲版本庫裏還有,所以可以恢復過來
#git checkout -- file
10、添加遠程庫
要關聯一個遠程庫,使用命令:
#git remote add origin git@server-name:path/repo-name.git;
關聯後,使用命令#git push -u origin master第一次推送master分支的所有內容;
此後,每次本地提交後,只要有必要,就可以使用命令#git push origin master推送最新修改;
11、從遠程庫克隆
Ssh協議:#git clone [email protected]:path/repo-name.git
https協議:#git clone https://github.com/path/repo-name.git
12、 創建與合併分支
(1)查看分支:git branch
(2)創建分支:git branch name
(3)切換分支:git checkout name
(4)創建+切換分支:git checkout -b name
(5)合併某分支到當前分支:git merge name
(6)刪除分支:git branch -d name
注:當Git無法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。
(7)用git log --graph命令可以看到分支合併圖。
13、分支管理策略
通常,合併分支時,如果可能,Git會用“Fast forward”模式,但這種模式下,刪除分支後,會丟掉分支信息。
如果要強制禁用“Fast forward”模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息。
#git merge --no-ff -m "merge with no-ff" name
因爲本次合併要創建一個新的commit,所以加上-m參數,把commit描述寫進去。
合併後,我們用git log看看分支歷史:
#git log --graph --pretty=oneline --abbrev-commit
在實際開發中,我們應該按照幾個基本原則進行分支管理:
首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;
那在哪幹活呢?幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;
你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合併就可以了。
所以,團隊合作的分支看起來就像這樣:
14、BUG分支(保存工作現場)
修復bug時,我們會通過創建新的bug分支進行修復,然後合併,最後刪除;
當手頭工作沒有完成時,先把工作現場git stash一下,然後去修復bug,修復後,再git stash pop,回到工作現場。
(1)保存當前工作現場,然後就可以創建bug分支:
#git stash
(2)修復完BUG後,切換爲之前分支併合並,刪除BUG分支然後回到工作分支,恢復工作現場:
#git stash list 查看儲藏的工作現場
恢復工作現場有兩個辦法:
一是用git stash apply恢復,但是恢復後,stash內容並不刪除,你需要用git stash drop來刪除;
另一種方式是用git stash pop,恢復的同時把stash內容也刪了:
你可以多次stash,恢復的時候,先用git stash list查看,然後恢復指定的stash,用命令:
$ git stash apply stash@{0}(git stash list 查看的結果)
15、創建一個新功能分支feature
開發一個新feature,最好新建一個分支;(創建分支-開發-提交-切回-合併-刪除新分支)
如果要丟棄一個沒有被合併過的分支,可以通過git branch -D name強行刪除。
16、多人協作
(1)查看遠程庫信息:# git remote
(2)查看更詳細的信息:#git remote –v
會顯示了可以抓取和推送的origin的地址。如果沒有推送權限,就看不到push的地址。
17、推送分支
推送分支,就是把該分支上的所有本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:
#git push origin branch-name
但是,並不是一定要把本地分支往遠程推送,那麼,哪些分支需要推送,哪些不需要呢?
(1)master分支是主分支,因此要時刻與遠程同步;
(2)dev分支是開發分支,團隊所有成員都需要在上面工作,所以也需要與遠程同步;
(3)bug分支只用於在本地修復bug,就沒必要推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
(4)feature分支是否推到遠程,取決於你是否和你的小夥伴合作在上面開發。
總之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,視你的心情而定!
18、抓取分支
多人協作的工作模式通常是這樣:
(1)首先,可以試圖用git push origin branch-name推送自己的修改;
(2)如果推送失敗,則因爲遠程分支比你的本地更新,需要先用git pull試圖合併;
(3)如果合併有衝突,則解決衝突(手動修改),並在本地提交(git add/git commit);
(4)沒有衝突或者解決掉衝突後,再用git push origin branch-name推送就能成功!
(5)如果git pull提示“no tracking information”,則說明本地分支和遠程分支的鏈接關係沒有創建,用命令git branch --set-upstream branch-name origin/branch-name。
這就是多人協作的工作模式,一旦熟悉了,就非常簡單。
在本地創建和遠程分支對應的分支,使用git checkout -b branch-name origin/branch-name,本地和遠程分支的名稱最好一致;
19、創建標籤
發佈一個版本時,我們通常先在版本庫中打一個標籤,這樣,就唯一確定了打標籤時刻的版本。將來無論什麼時候,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。所以,標籤也是版本庫的一個快照。
Git的標籤雖然是版本庫的快照,但其實它就是指向某個commit的指針(跟分支很像對不對?但是分支可以移動,標籤不能移動),所以,創建和刪除標籤都是瞬間完成的。
(1)命令git tag tagname用於新建一個標籤,默認爲HEAD,
(2)也可以指定一個commit id;
#git branch 查看分支信息
#git tag tagname(v1.0) “commit id” 給指定分支創建標籤
注意,標籤不是按時間順序列出,而是按字母排序的。可以用git show tagname查看標籤信息:
(1) -a tagname -m "blablabla..."可以指定標籤信息;
(2)-s tagname -m "blablabla..."可以用PGP簽名標籤;
(3) 命令git tag可以查看所有標籤;
20、操作標籤(刪除、推送)
(1)命令git push origin tagname可以推送一個本地標籤;
(2)命令git push origin --tags可以推送全部未推送過的本地標籤;
(3)命令git tag -d tagname可以刪除一個本地標籤;
(4)命令git push origin :refs/tags/tagname可以刪除一個遠程標籤。
21、忽略特殊文件
有些時候,你必須把某些文件放到Git工作目錄中,但又不能提交它們。在Git工作區的根目錄下創建一個特殊的.gitignore文件,然後把要忽略的文件名填進去,並將.gitignore文件提交到Git,Git就會自動忽略這些文件。
不需要從頭寫.gitignore文件,GitHub已經爲我們準備了各種配置文件,只需要組合一下就可以使用了。所有配置文件可以直接在線瀏覽:https://github.com/github/gitignore
忽略文件的原則是:
忽略操作系統自動生成的文件,比如縮略圖等;
忽略編譯生成的中間文件、可執行文件等,也就是如果一個文件是通過另一個文件自動生成的,那自動生成的文件就沒必要放進版本庫,比如Java編譯產生的.class文件;
忽略你自己的帶有敏感信息的配置文件,比如存放口令的配置文件。
22、 配置別名
有沒有經常敲錯命令?比如git status?status這個單詞真心不好記。
(1) 如果敲git st就表示git status那就簡單多了,當然這種偷懶的辦法我們是極力贊成的。
我們只需要敲一行命令,告訴Git,以後st就表示status:
$ git config --global alias.st status
(2)當然還有別的命令可以簡寫,很多人都用co表示checkout,ci表示commit,br表示branch:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch
--global參數是全局參數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。
(3) 在撤銷修改一節中,我們知道,命令git reset HEAD file可以把暫存區的修改撤銷掉(unstage),重新放回工作區。既然是一個unstage操作,就可以配置一個unstage別名:
$ git config --global alias.unstage 'reset HEAD'
當你敲入命令:
$ git unstage test.py
實際上Git執行的是:
$ git reset HEAD test.py
(4)配置一個git last,讓其顯示最後一次提交信息:
$ git config --global alias.last 'log -1'
這樣,用git last就能顯示最近一次的提交:
$ git last
commit adca45d317e6d8a4b23f9811c3d7b7f0f180bfe2
Merge: bd6ae48 291bea8
Author: Michael Liao <[email protected]>
Date: Thu Aug 22 22:49:22 2013 +0800
merge & fix hello.py
(5)甚至還有人喪心病狂地把lg配置成了:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
來看看git lg的效果:
23、 配置文件
配置Git的時候,加上--global是針對當前用戶起作用的,如果不加,那隻針對當前的倉庫起作用。
(1)配置文件放哪了?每個倉庫的Git配置文件都放在.git/config文件中:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = [email protected]:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
別名就在[alias]後面,要刪除別名,直接把對應的行刪掉即可。
(2)而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig中:
$ cat .gitconfig
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = [email protected]
配置別名也可以直接修改這個文件,如果改錯了,可以刪掉文件重新通過命令配置。
參考資料:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
http://rogerdudler.github.io/git-guide/index.zh.html
http://www.open-open.com/lib/view/open1332904495999.html