基礎知識和命令先參考:使用git和github管理本身的項目---基礎操做學習linux
一般,合併分支時,若是可能,Git會用Fast forward
模式,但這種模式下,刪除分支後,會丟掉分支信息。git
若是要強制禁用Fast forward
模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就能夠看出分支信息。github
下面咱們實戰一下--no-ff
方式的git merge
:數據庫
git checkout -b dev
建立並切換到dev分支bootstrap
vim readme.txt
修改readme.txt文件ubuntu
git add readme.txt
vim
git commit -m "add merge"
提交一個新的commitsegmentfault
git checkout master
切回master分支安全
git merge --no-ff -m "merge with with no-ff" dev
準備合併dev分支,注意--no-ff
參數表示禁用Fast forward,由於本次合併要建立一個新的commit,因此加上-m
參數,把commit描述寫進去服務器
git log --graph --pretty=oneline --abbrev-commit
合併後查看分支歷史
合併分支時,加上--no-ff參數就能夠用普通模式合併,合併後的歷史有分支,能看出來曾經作過合併,而fast forward合併就看不出來曾經作過合併。
在實際開發中,咱們應該按照幾個基本原則進行分支管理:
首先,master
分支應該是很是穩定的,也就是僅用來發布新版本,平時不能在上面幹活
那在哪裏幹活呢?幹活都在dev
分支上,也就是說,dev
分支是不穩定的,到某個時候,好比2.0版本發佈時,再把dev
分支合併到master
上,在master
分支發新版本
你和你的小夥伴每一個人都在dev
分支上幹活,每一個人都有本身的分支,時不時往dev
分支上合併就能夠了
因此,團隊合做的分支看起來就像這個樣子:
Git分支十分強大,在團隊開發中應該充分應用。
軟件開發中,bug就像是屢見不鮮同樣。有了bug就須要修復,在Git中,因爲分支是如此的強大,因此每一個bug均可以經過一個新的臨時分支來修復,修復後,合併分支,而後將臨時分支刪除。
當你街道一個修復代號爲101的bug的任務的時候,很天然的,你想建立一個分支issue-101
來修復它,可是,等等,當前正在dev
上進行的工做尚未提交:
git status
查看狀態
並非你不想提交,而是工做只進行到一半,還無法提交,預計完成還需1天時間。可是,必須在兩個小時內修復該bug,怎麼辦?
幸虧,Git還提供了一個stash功能,能夠把當前工做現場「儲藏」起來,等之後恢復現場後繼續工做:
git stash
用該命令查看工做區,就是乾淨的(除非有沒有被Git管理的文件),所以能夠放心的建立分支來修復bug了。
git checkout master
從dev分支切換回master
git checkout -b issue-101
假定須要在master分支上修復,就從master
建立臨時分支
假設如今修復好了bug,本例中,就假如在readme.txt文件中作了修改
git add readme.txt
git commit -m "fic bug 101"
修改以後提交
git checkout master
從issue-101切換回master
git merge --no-ff -m "merged bug fix 101" issue-101
合併分支選擇不適用Fast forward模式,而後添加必要的描述信息
git branch -d issue-101
刪除issue-101這個臨時bug修復分支
太棒了,bug搞定了,如今能夠回到dev
分支幹活了
git checkout dev
切換回dev分支
git status
能夠看出工做區是乾淨的,那麼剛纔的工做現場存在哪裏呢?
git stash list
看到工做現場還在,Git吧stash內容存在某個地方了,可是須要恢復一下
方法一git stash apply
,可是回覆後,stash內容並不刪除,你須要使用git stash drop
來刪除
方法二git stash pop
,恢復的同時也把stas內容刪除了
git stash list
再用git stash list查看,就看不到任何stash內容了
你能夠屢次stash
,恢復的時候,先用giit stash list
查看,而後恢復指定的stash,使用以下的命令
git stash apply stash@{0}
修復bug時,咱們會經過建立新的bug分支進行修復,而後合併,最後刪除。
當手頭工做沒有完成時,先把工做現場git stash一下,而後去修復bug,修復後,再git stash pop,回到工做現場。
軟件開發中,總有無窮無盡的新的功能要不斷添加進來。
添加一個新功能時,你確定不但願由於一些實驗性質的代碼,把主分支搞亂了,因此,每添加一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
如今,你終於接到了一個新任務:開發代號爲Vulcan的新功能,該功能計劃用於下一代星際飛船。軟件開發中,總有無窮無盡的新的功能要不斷添加進來。
添加一個新功能時,你確定不但願由於一些實驗性質的代碼,把主分支搞亂了,因此,每添加一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
如今,你終於接到了一個新任務:開發代號爲Vulcan的新功能,該功能計劃用於下一代星際飛船。因而開始準備工做
git checkout -b feature-vulcan
在dev分支上建立而且換到feature-vulcan分支,用來開發新功能
假如如今通過必定的時間後,工做完成了
git add vulcan.py
git status
查看狀態
git commit -m "add feature vulcan"
提交
git checkout dev
切換回dev分支
一切順利的話,feature分支和bug分支是相似的,合併,而後刪除。可是,就在此時,接到上級命令,因經費不足,新功能必須取消!雖然白乾了,可是這個分支仍是必須就地銷燬,不要再合併了:
git branch -d feature-vulcan
銷燬失敗。Git友情提醒,feature-vulcan分支尚未被合併,若是刪除,將丟失掉修改,若是要強行刪除,須要使用命令git branch -D feature-vulcan。
git branch -D feature-vulcan
當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,而且,遠程倉庫的默認名稱是origin。
推送分支
git remote
查看遠程庫的信息
git remote -v
顯示更爲詳細的信息
git push origin master
推送分支,就是把該分支上的全部本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上。
git push origin dev
也能夠推送到其餘的分支,好比dev分支
可是,並非必定要把本地分支往遠程推送,那麼,哪些分支須要推送,哪些不須要呢?master分支是主分支,所以要時刻與遠程同步;dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。總之,就是在Git中,分支徹底能夠在本地本身藏着玩,是否推送,視你的心情而定!
抓取分支
多人協做時,你們都會往master和dev分支上推送各自的修改。
git clone git@github.com:michaelliao/learngit.git
如今,模擬一個你的小夥伴,能夠在另外一臺電腦(注意要把SSH Key添加到GitHub)或者同一臺電腦的另外一個目錄下克隆。
git branch
當你的小夥伴從遠程庫clone時,默認狀況下,你的小夥伴只能看到本地的master分支,因此執行這條命令只能看到master分支
git checkout -b dev origin/dev
如今,你的小夥伴要在dev分支上開發,就必須建立遠程origin的dev分支到本地,因而他用這個命令建立本地dev分支
git commit -m "add /usr/bin/env"
如今,他就能夠在dev上繼續修改,而後,時不時地把dev分支push到遠程。
git add hello.py
git commit -m "add coding: utf-8"
git push origin dev
你的小夥伴已經向origin/dev分支推送了他的提交,而碰巧你也對一樣的文件做了修改,並試圖推送。推送失敗,由於你的小夥伴的最新提交和你試圖推送的提交有衝突。
git pull
解決辦法也很簡單,Git已經提示咱們,先用git pull把最新的提交從origin/dev抓下來,而後,在本地合併,解決衝突,再推送。
git branch --set-upstream dev origin/dev
git pull也失敗了,緣由是沒有指定本地dev分支與遠程origin/dev分支的連接,根據提示,設置dev和origin/dev的連接。
git pull
再次pull,這回git pull成功,可是合併有衝突,須要手動解決,解決的方法和分支管理中的解決衝突徹底同樣
git commit -m "merge & fix hello.py"
git push origin dev
解決衝突後,再提交,再push
所以,多人協做的工做模式一般是這樣的:
首先,能夠試圖用git push origin branch-name
推送本身的修改
若是推送失敗,則由於遠程分支比你的本地更新,須要先用git pull
試圖合併
若是合併有衝突,則解決衝突,並在本地提交
沒有衝突或者解決掉衝突以後,再用git push origin branch-name
推送就能成功
若是git pull提示「no tracking information」,則說明本地分支和遠程分支的連接關係沒有建立,用命令git branch --set-upstream branch-name origin/branch-name。這就是多人協做的工做模式,一旦熟悉了,就很是簡單。
發佈一個版本時,咱們一般先在版本庫中打一個標籤,這樣,就惟一肯定了打標籤時刻的版本。未來不管何時,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。因此,標籤也是版本庫的一個快照。
Git的標籤雖然是版本庫的快照,但其實它就是指向某個commit的指針(跟分支很像對不對?可是分支能夠移動,標籤不能移動),因此,建立和刪除標籤都是瞬間完成的。
git branch
查看當前有哪些分支
git checkout master
在Git中打標籤很是簡單,首先,切換到須要打標籤的分支上
git tag tagnamev1.0
打一個新標籤
git tag
查看全部標籤
默認標籤是打在最新提交的commit上的(也就是HEAD
)。有時候,若是忘了打標籤,好比,如今已是週五了,但應該在週一打的標籤沒有打,怎麼辦?
git log --pretty=oneline --abbrev-commit
方法是找到歷史提交的commit id,而後打上就能夠了,這時候顯示了提交的歷史信息 ,假若有這麼一條就是你想打標籤的歷史commit:6224937 add merge
git tag tagnamev2.0 6224937
就能夠給此次提交打標籤了
git tag
能夠查看標籤信息,注意,標籤不是按時間順序列出,而是按字母排序的
git show tagnamev2.0
查看具體的某個標籤的信息
git tag -a v0.1 -m "version 0.1 released" 3628164
還能夠建立帶有說明的標籤,用-a指定標籤名,-m指定說明文字
git show v0.1
查看具體的某個標籤的信息,能夠看到說明文字
git tag -s v0.2 -m "signed version 0.2 released" fec145a
還能夠經過-s用私鑰簽名一個標籤,簽名採用PGP簽名,所以,必須首先安裝gpg(GnuPG),若是沒有找到gpg,或者沒有gpg密鑰對,就會報錯
git show v0.2
用命令git show <tagname>能夠看到PGP簽名信息,用PGP簽名的標籤是不可僞造的,由於能夠驗證PGP簽名。
git tag -d v0.1
假如標籤打錯了,也能夠刪除,由於建立的標籤都只存儲在本地,不會自動推送到遠程。因此,打錯的標籤能夠在本地安全刪除。
git push origin v1.0
要推送某個標籤到遠程
git push origin --tags
或者,一次性推送所有還沒有推送到遠程的本地標籤
git tag -d v0.9
若是標籤已經推送到遠程,要刪除遠程標籤就麻煩一點,先從本地刪除
git push origin :refs/tags/v0.9
而後,從遠程刪除。刪除命令也是push,可是格式要注意
如何參與一個開源項目呢?好比人氣極高的bootstrap項目,這是一個很是強大的CSS框架。
你能夠訪問它的項目主頁https://github.com/twbs/boots...,點「Fork」就在本身的帳號下克隆了一個bootstrap倉庫
git clone git@github.com:yourname/bootstrap.git
而後,從本身的帳號下clone
必定要從本身的帳號下clone倉庫,這樣你才能推送修改。若是從bootstrap的做者的倉庫地址git@github.com:twbs/bootstrap.git克隆,由於沒有權限,你將不能推送修改。
Bootstrap的官方倉庫twbs/bootstrap、你在GitHub上克隆的倉庫my/bootstrap,以及你本身克隆到本地電腦的倉庫,他們的關係就像下圖顯示的那樣:
若是你想修復bootstrap的一個bug,或者新增一個功能,馬上就能夠開始幹活,幹完後,往本身的倉庫推送。
若是你但願bootstrap的官方庫能接受你的修改,你就能夠在GitHub上發起一個pull request。固然,對方是否接受你的pull request就不必定了。
若是你沒能力修改bootstrap,但又想要試一把pull request,那就Fork一下廖雪峯的倉庫:https://github.com/michaellia...,建立一個your-github-id.txt
的文本文件,好比個人:xumenger.txt
,寫點本身學習Git的心得,而後推送一個pull request給他,他會視心情而定是否接受。
以前已經說過在使用以前必須先配置user.name
和user.email
,不然後面commit的時候可能會有錯誤,實際上git還有不少可配置的:
git config --global color.ui true
讓Git顯示顏色,會讓命令輸出看起來更醒目,本身去試試一些git命令的輸出看看是否是有色!
有些時候,你必須把某些文件放到Git工做目錄中,但又不能提交它們,好比保存了數據庫密碼的配置文件啦,等等,每次git status都會顯示Untracked files ...,有強迫症的童鞋內心確定不爽。
好在Git考慮到了你們的感覺,這個問題解決起來也很簡單,在Git工做區的根目錄下建立一個特殊的.gitignore文件,而後把要忽略的文件名填進去,Git就會自動忽略這些文件。
不須要從頭寫.gitignore文件,GitHub已經爲咱們準備了各類配置文件,只須要組合一下就可使用了。全部配置文件能夠直接在線瀏覽:https://github.com/github/git...
忽略文件的原則是:
忽略操做系統自動生成的文件,好比縮略圖等;
忽略編譯生成的中間文件、可執行文件等,也就是若是一個文件是經過另外一個文件自動生成的,那自動生成的文件就不必放進版本庫,好比Java編譯產生的.class文件;
忽略你本身的帶有敏感信息的配置文件,好比存放口令的配置文件。
舉個例子
假設你在Windows下進行Python開發,Windows會自動在有圖片的目錄下生成隱藏的縮略圖文件,若是有自定義目錄,目錄下就會有Desktop.ini文件,所以你須要忽略Windows自動生成的垃圾文件:
# Windows: Thumbs.db ehthumbs.db Desktop.ini
而後,繼續忽略Python編譯產生的.pyc、.pyo、dist等文件或目錄:
# Python: *.py[cod] *.so *.egg *.egg-info dist build
加上你本身定義的文件,最終獲得一個完整的.gitignore文件,內容以下:
# Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa
最後一步就是把.gitignore也提交到Git,就完成了!固然檢驗.gitignore的標準是git status命令還會不會再說working directory clean。.gitignore文件自己要放到版本庫裏,而且能夠對.gitignore作版本管理!
使用Windows的童鞋注意了,若是你在資源管理器裏新建一個.gitignore文件,它會很是弱智地提示你必須輸入文件名,可是在文本編輯器裏「保存」或者「另存爲」就能夠把文件保存爲.gitignore了。
再次建議:有錢的買mac,沒錢的用ubuntu--或者其餘的linux發行版、被逼無奈的用Windows--可是被逼之餘的自主時間必定要遠離Windows。
給Git配置好別名,就能夠輸入命令時偷個懶。咱們鼓勵偷懶。
git config --global alias.st status
有沒有常常敲錯命令?好比git status?status這個單詞真心很差記。若是敲git st就表示git status那就簡單多了,固然這種偷懶的辦法咱們是極力同意的。
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
不少人都用co表示checkout,ci表示commit,br表示branch
git ci -m "bala bala bala..."
之後提交就能夠簡寫成這樣
git config --global alias.unstage 'reset HEAD'
在撤銷修改一節中,咱們知道,命令git reset HEAD file
能夠把暫存區的修改撤銷掉(unstage),從新放回工做區。既然是一個unstage操做,就能夠配置一個unstage別名
git unstage test.py
當你敲入此命令,實際上Git執行的是:git reset HEAD test.py
git config --global alias.last 'log -1'
配置一個git last,讓其顯示最後一次提交信息
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
的效果是這樣的
配置文件
配置Git的時候,加上--global
是針對當前用戶起做用的,若是不加,那隻針對當前的倉庫起做用。
配置文件放哪了?每一個倉庫的Git配置文件都放在.git/config
文件中:
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = git@github.com:michaelliao/learngit.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [alias] last = log -1
別名就在[alias]
後面,要刪除別名,直接把對應的行刪掉便可。
而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig
中:
$ cat .gitconfig [alias] co = checkout ci = commit br = branch st = status [user] name = Your Name email = your@email.com
配置別名也能夠直接修改這個文件,若是改錯了,能夠刪掉文件從新經過命令配置。
若是須要的話,請本身參考廖雪峯的教程