Git使用總結(jié)五:分支管理

前些時間,公司產(chǎn)品經(jīng)理針對司機端提出一個微信及支付寶二維碼掃碼支付需求,需求不急,但也是剛性任務(wù),于是我在會后便火急火燎開干,期間碰到一些問題獲取了一些經(jīng)驗,想分享給各位。

第一個問題,期間,或許因為公司反復(fù)修網(wǎng)造成GitLab地址變動,管理GitLab的后臺并沒有多余的時間來維護,所以短時間內(nèi),并不能將本地的修改 push 到遠程。這種情況下,我將每次的修改 commit 到本地,等GitLab好了再 push,對此我深刻感受到Git的好處。

第二個問題,在公司我負責(zé)iOS移動端的獨立開發(fā)與維護。由于是獨立開發(fā),使用Git時,我一般在 devfix bug 或者改需求。此次,我需求完成一半,測試那邊給出反饋,我放下手頭需求,緊急 fix bugcommit 到本地后,在無法 push 到遠程的情況下,我需要緊急提交一個新版本。問題來了,由于GitLab未修復(fù),我無法clone上個版本到本地來fix bug,又因為我dev分支上同時fix bug和迭代需求,本地也不是上一個版本。

創(chuàng)建與合并分支

在Git里,每次提交,Git把提交串成一個分支,這個分支是主分支,即 master 分支。HEAD 不是指向提交,而是指向 mastermaster 才指向提交,所以,HEAD指向的是當(dāng)前分支。

Git創(chuàng)建一個 dev 分支時很快,因為除了需要增加一個 dev 指針,改變 HEAD 的指向,工作區(qū)的文件沒有變。

Git合并 dev 分支到 master 分支也很快,在 dev 上完成工作后,直接把 master 指向 dev 當(dāng)前的提交,就完成了合并。合并過程中,指針指向改變,工作區(qū)內(nèi)容同樣沒有變。

  • 創(chuàng)建 dev 分支,然后切換到 dev 分支
git checkout -b dev
  • 創(chuàng)建分支
git branch <name>
  • 切換分支
git checkout <name>
  • git branch 查看當(dāng)前分支
$ git branch
* dev
  master
  • git merge 命令用于合并指定分支到當(dāng)前分支
git merge <name>
  • 刪除分支
git branch -d <name>

解決沖突

  • 創(chuàng)建并切換 feature 分支
$ git checkout -b feature
Switched to a new branch feature
  • 修改工作區(qū)內(nèi)容后,在 feature 分支上提交修改并且將暫存區(qū)的修改 commit 到當(dāng)前分支
$ git add readme.txt
$ git commit -m "and simple"
[feature 75a857c] and simple
1 file changed, 1 insertion(+), 1 deletion(-)
  • 切換到 master 分支,系統(tǒng)將會提示當(dāng)前 master 分支彼遠程的 master 分支要超前一個提交
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit
  • master 分支上把工作區(qū)內(nèi)容進行修改,并且提交
$ git add readme.txt
$ git commit -m "& simple"
[master 400b400] & simple
1 file changed, 1 insertion(+), 1 deletion(-)
  • 此刻在master分支和feature分支都要提交的情況下,Git無法進行快速合并,如果試圖把各自的修改合并,將會造成沖突。
$ git merge feature
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
  • Git將會提示,readme.txt文件存在沖突,必須手動解決沖突后再提交,我們一般使用 git status 了解我們沖突的文件。
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      readme.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
  • 直接查看readme.txt文件夾下內(nèi)容,Git用 <<<<<<<=======>>>>>>> 標記出不同分支的內(nèi)容,我們修改文件夾下內(nèi)容使 feature 分支和 master 分支保持一致后,再提交。

  • 使用帶參數(shù)的 git log 也可以看到分支的合并情況

$ git log --graph --pretty=oneline --abbrev-commit
*   59bc1cb conflict fixed
|\
| * 75a857c AND simple
* | 400b400 & simple
|/
* fec145a branch test
...
  • 最后刪除分支
$ git branch -d feature
Deleted branch feature (was 75a857c).
  • 所以說,當(dāng)Git無法自動合并分支時,就必須首先解決沖突,解決沖突后,再提交,合并完成。使用 git log --graph 命令可以查看分支合并圖

分支管理策略

在解決沖突時,我們提到了快速合并,通常,我們在合并分支時,Git會使用 Fast forward 模式,在 Fast forward 模式下,刪除分支后,會丟失分支信息。

所以,我們會強制禁用 Fast forward 模式,Git會在 merge 時生成一個新的 commit,這樣我們可以在分支歷史上查看分支信息。

--no-ff方式的git merge

  • 首先,創(chuàng)建并切換 dev 分支
$ git checkout -b dev 
Switched to a new branch dev
  • 修改工作區(qū)readme.txt文件,并提交一個新的 commit
$ git add readme.txt 
$ git commit -m "add merge"
[dev 6224937] add merge
 1 file changed, 1 insertion(+)
  • 切換回 master
$ git checkout master
Switched to branch 'master'
  • 合并 dev 分支時,注意使用 --no-ff 參數(shù),表示禁用 Fast forward
$ git merge --no-ff -m "merge with --no-ff" dev
Merge made by the 'recursive' strategy.
 readme.txt |    1 +
 1 file changed, 1 insertion(+)
  • 合并后我們使用 git log 查看分支歷史
$ git log --graph --pretty=oneline --abbrev-commit
*   7825a50 merge with no-ff
|\
| * 6224937 add merge
|/
*   59bc1cb conflict fixed
...

分支策略

其實,我們在實際開發(fā)中,應(yīng)該按照幾個基本原則進行分支管理:

  1. 首先,master 分支應(yīng)該是最穩(wěn)定的,也就是說,我們平時不能在 master 上干活,master 分支僅用來發(fā)布版本使用。

  2. 如果要干活,我們應(yīng)該創(chuàng)建并切換一個分支,這個分支就是 dev 分支。也就是說,dev 分支是不穩(wěn)定的,平時我們各自在 dev 分支上干活,每個人有自己的分支,不斷往 dev 分支上合并,等到版本發(fā)布時,再把 dev 分支合并到 master 上。

Bug分支

當(dāng)前,正在 dev 上的工作還沒提交,我們需要經(jīng)緊急修復(fù)一個bug,很自然地,需要創(chuàng)建一個 bug 分支來修復(fù)這個bug。有人會有疑問,為什么不把 dev 上工作區(qū)的修改先進行提交,其實我們并不是不想提交,而是工作進行到一半無法提交。那么,Git為我們提供一個 stash 功能,先把當(dāng)前工作現(xiàn)場“儲藏”起來,等恢復(fù)現(xiàn)場后繼續(xù)工作。

$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
  • git stash 后,我們用 git status 查看工作區(qū),工作區(qū)是干凈的,我們可以放心創(chuàng)建分支修復(fù)bug。

  • 確定在那個分支上修復(fù)bug,就在那個分支上創(chuàng)建bug分支。此次我們在 master 上修復(fù),就從 master 上創(chuàng)建臨時分支。由于創(chuàng)建的 bug 分支是臨時分支,修復(fù)bug后,切換到 master 分支,完成合并,最后刪除 bug 分支。

  • 接著我們回到 dev 干活,使用 git status 查看工作區(qū)狀態(tài),發(fā)現(xiàn)工作區(qū)是干凈的,這是我們需要使用 git stash list 查看存的工作現(xiàn)場。

$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
  • 使用 git stash apply 恢復(fù),但是恢復(fù)后,stash內(nèi)容不會刪除,需要使用 git stash drop 刪除stash內(nèi)容。

  • 或者,使用 git stash pop,恢復(fù)的同時把stash內(nèi)容也刪除了。

$ git stash pop
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   readme.txt
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
  • 使用 git stash pop 后,使用 git stash list 查看,就看不到stash內(nèi)容了。

Feature分支

一般情況下,添加一個新功能,需要創(chuàng)建一個 feature 分支,feature 分支作為臨時開發(fā)新功能的分支最終要合并到 dev 分支,也就是說,我們添加一個新功能,并不是在 dev 上進行開發(fā),而是要創(chuàng)建一個 feature 分支,而這個 feature 分支用于臨時開發(fā)一個新功能,是一個臨時分支。

  • 其實,feature 分支和 bug 分支類似,創(chuàng)建切換,合并,然后刪除。

  • 取消新功能時,使用 git branch -d <name> 刪除分支,但是會提示銷毀失敗,這時需要強行刪除分支,使用命令 git branch -D <name>

$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 756d4af).
  • 所以,如果要丟棄一個沒有被合并的分支,可以通過 git branch -D <name> 強行刪除這個分支。

多人協(xié)作

真正意義上,Git的價值還是體現(xiàn)在團隊協(xié)作作用上,而那些命令其實僅僅起到輔助協(xié)作的作用,如果是獨立開發(fā)并不能深刻體會到這種協(xié)作的作用,但是如果進入純技術(shù)公司團隊,可能Git的這種協(xié)作價值才能真正的體現(xiàn)出來。

  • 從遠程倉庫 clone 時,實際上Git自動把本地 master 分支和遠程 master 分支對應(yīng)起來了,并且,遠程倉庫默認的名稱是 origin

  • 所以說,我們使用 git remote 查看遠程倉庫的信息

$ git remote
origin
  • 或者,用 git remote -v 查看遠程庫詳細信息
$ git remote -v
origin  git@github.com:michaelliao/learngit.git (fetch)
origin  git@github.com:michaelliao/learngit.git (push)

推送分支

  • master 分支在本地作為主分支,要時刻與遠程倉庫同步。

  • dev 分支是開發(fā)分支,團隊所有成員都需要在 dev 分支上工作,所以 dev 分支同樣需要與遠程同步。

  • bug 分支作為臨時分支,只在本地修復(fù)bug,沒有必要推送到遠程,可能一周推送一次。

  • feature 分支同樣是臨時分支,但是,feature 分支是否推送到分支,取決于是否團隊協(xié)作,如果是獨立開發(fā),feature 分支沒有必要推送到遠程,如果協(xié)作開發(fā),需要推送到遠程,與遠程保持同步。

抓取分支

  • 從遠程庫 clone 時默認只能看到本地的 master 分支,我們可以使用 git stauts 查看。
$ git branch
* master
  • 要在 dev 分支上開發(fā),必須創(chuàng)建遠程 origindev 分支到本地,可以使用 git checkout -b dev origin/dev 命令創(chuàng)建本地 dev 分支。
$ git checkout -b dev origin/dev
  • 可以在本地創(chuàng)建的這個 dev 分支上修改,并且把修改 commitdev 分支,然后把 dev 分支 push 到遠程。
$ git commit -m "add /usr/bin/env"
[dev 291bea8] add /usr/bin/env
 1 file changed, 1 insertion(+)
$ git push origin dev
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 349 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
   fc38031..291bea8  dev -> dev
  • 由于你已經(jīng)向 origin/dev分支 推送了提交,而devB碰巧對同樣的文件做了修改,并且試圖推送,由于我的最新提交和devB試圖推送的提交有沖突,所以,推送失敗。
$ git add hello.py 
$ git commit -m "add coding: utf-8"
[dev bd6ae48] add coding: utf-8
 1 file changed, 1 insertion(+)
$ git push origin dev
To git@github.com:michaelliao/learngit.git
 ! [rejected]        dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
  • 這時,Git提醒,先用 git pull 把最新的提交從 origin/dev 抓取下來,然后,在本地合并,先解決沖突,然后再推送到遠程。
$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
   fc38031..291bea8  dev        -> origin/dev
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 dev origin/<branch>
  • git pull 失敗,因為未指定本地 dev 分支和遠程 origin/dev 分支鏈接,所以,設(shè)置 dev 和遠程 origin/dev 的鏈接。
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
  • git pull 成功后,git merge 合并存在沖突,先手動解決沖突,然后提交,最后 push 到遠程。
$ git commit -m "merge & fix hello.py"
[dev adca45d] merge & fix hello.py
$ git push origin dev
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 747 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
   291bea8..adca45d  dev -> dev
  • 請記住,如果 git pull 提示“no tracking information“,則說明本地分支和遠程分支的鏈接關(guān)系沒有創(chuàng)建,使用命令 git branch --set-upstream branch-name origin/branch-name,以上就是多人協(xié)作的工作模式。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內(nèi)容

  • 1.git的安裝 1.1 在Windows上安裝Git msysgit是Windows版的Git,從https:/...
    落魂灬閱讀 12,695評論 4 54
  • 聲明:這篇文章來源于廖雪峰老師的官方網(wǎng)站,我僅僅是作為學(xué)習(xí)之用 Git簡介 Git是什么? Git是目前世界上最先...
    橫渡閱讀 3,974評論 3 27
  • 遠程倉庫 到目前為止,我們已經(jīng)掌握了如何在Git倉庫里對一個文件進行時光穿梭,你再也不用擔(dān)心文件備份或者丟失的問題...
    歸云丶閱讀 1,970評論 0 5
  • 石頭小記 一塊奇異形狀的石頭碎了,散在桌子上,一陣悲傷。 它經(jīng)歷了從大石山到大石頭再到小石頭的過程,從遙遠的...
    碧風(fēng)寒影閱讀 403評論 0 3
  • angularjs是由谷歌公司開發(fā)并維護的一款開源的javascript框架,其特點用于構(gòu)建單頁面應(yīng)用(SPA),...
    家娃閱讀 396評論 1 1