GIT使用

一、常用命令介紹
1.1 命令行介紹
1.1.1 Git 全局設置

$ git config --global user.name "knight"
$ git config --global user.email "[email protected]"

1.1.2 創建一個新倉庫(本地)

$ git clone http://git.dayuan.cc/practice/git-exmple.git
cd git-exmple
$ touch README.md
$ git add README.md
$ git commit -m "add README"
$ git push -u origin master

1.1.3 在已存在的目錄中創建倉庫

cd existing_folder
$ git init
$ git remote add origin http://git.dayuan.cc/practice/git-exmple.git
$ git add .
$ git commit -m "Initial commit"
$ git push -u origin master

1.1.4 將本地已存在的倉庫推送到遠程倉庫

cd existing_repo
$ git remote rename origin old-origin
$ git remote add origin http://git.dayuan.cc/practice/git-exmple.git
$ git push -u origin --all
$ git push -u origin --tags

1.1.5 查看分支相關命令

$ git branch -r; //查看遠程分支
$ git branch; //查看本地分支
$ git branch -a; //查看所有分支

1.1.6 拉取遠程分支並創建本地分支

// dev2爲遠程分支,dev1爲本地分支
$ git checkout -b dev1 origin/dev2; 

從遠程分支dev拉取到本地並且創建本地分支dev,且倆者之間建立映射關係,同時當前分支會切換到dev1

//dev2爲遠程分支,dev1爲本地分支
$ git fetch origin dev2:dev1;

使用該方式會在本地新建分支dev1,但是不會自動切換到該本地分支dev1,需要手動checkout。採用此種方法建立的本地分支不會和遠程分支建立映射關係。
1.1.7 建立本地分支與遠程分支的映射關係(或者爲跟蹤關係track)
這樣使用git pull或者git push時就不必每次都要指定從遠程的哪個分支拉取合併和推送到遠程的哪個分支了。

$ git branch -vv

輸出映射關係

// dev爲遠程分支名
$ git branch -u origin/dev

將當前本地分支與遠程分支建立映射關係

$ git branch --unset-upstream 

撤銷當前本地分支與遠程分支的映射關係
1.1.8 切換當前本地分支

// dev爲本地分支名
$ git checkout dev;

1.1.9 拉取遠程分支代碼

$ git pull

使用的前提是當前分支需要與遠程分支之間建立映射關係
1.1.10 推送本地分支代碼到遠程分支

$ git push

使用的前提是當前分支需要與遠程分支之間建立映射關係
1.1.11 合併分支
場景:現在有dev本地分支與遠程分支,master本地分支與遠程分支
現在將dev的分支代碼合併到master主幹上
思路步驟 :

1. 切換到本地分支dev上,並且pull拉取一下遠程dev分支上的改動地方
2.將所有本地修改進行commit並且push到遠程dev分支上,保證沒有遺漏的,確保當前本地dev與遠程dev是一致的
3.將當前本地分支切換到本地master上
4.將本地分支dev合併到本地master上
5.將本地已經合併了dev分支的master進行push到遠程master上

大概思路就是這樣。需要注意的是在進行merge(合併)的時候需要禁用fast-forward模式
具體的合併命令: git merge --no-ff dev (dev爲本地被合併的分支名字)

二、Gitflow總覽
在這裏插入圖片描述
從上圖可以看到主要包含下面幾個分支:
master : 主分支,主要用來版本發佈。
develop:日常開發分支,該分支正常保存了開發的最新代碼。
feature:具體的功能開發分支,只與 develop 分支交互。
release:release分支可以認爲是master 分支的未測試版。比如說某一期的功能全部開發完成,那麼就將 develop 分支合併到 release 分支,測試沒有問題並且到了發佈日期就合併到master 分支,進行發佈。
hotfix:線上 bug 修復分支。
除此之後還可以有 fast-track 等分支。

2.1 主分支
主分支包括 master 分支和 develop 分支。master 分支用來發布,HEAD 就是當前線上的運行代碼。develop分支就是我們的日常開發。使用這兩個分支就具有了最簡單的開發模式:develop分支用來開發功能,開發完成並且測試沒有問題則將 develop分支的代碼合併到 master分支併發布。
在這裏插入圖片描述
這引入了幾個問題:
develop分支只有發佈完了才能進行下一個版本開發,開發會比較緩慢。
線上代碼出現 bug 如何進行 bug 修復。
帶着這兩個問題往下看。

2.2 輔助分支
主要介紹的輔助分支如下:
feature分支
release分支
hotfix分支
通過這些分支,我們可以做到:團隊成員之間並行開發,feature track更加容易,開發和發佈並行以及線上問題修復。

2.2.1 Feature 分支
feature分支用來開發具體的功能,一般 fork 自 develop分支,最終可能會合併到develop分支。比如我們要在下一個版本增加功能1、功能2、功能3。那麼我們就可以起三個feature分支:feature1,feature2,feature3。(feature分支命名最好能夠自解釋,這並不是一種好的命名。)隨着我們開發,功能1和功能2都被完成了,而功能3因爲某些原因完成不了,那麼最終 feature1 和 feature2分支將被合併到 develop分支,而 feature3分支將被幹掉。

在這裏插入圖片描述
我們來看幾個相關的命令。

2.2.1.1 新建feature分支
從 develop 分支建一個 feature 分支,並切換到 feature 分支

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

2.2.1.2 合併feature 分支到 develop

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature
$ git push origin develop

上面我們 merge 分支的時候使用了參數 --no-ff,ff 是fast-forward的意思,–no-ff就是禁用fast-forward。關於這兩種模式的區別如下圖。(可以使用 sourceTree 或者命令git log --graph查看。)
在這裏插入圖片描述
看了上面的圖,那麼使用非fast-forward模式來 merge 的好處就不言而喻了:我們知道哪些commit 是某些feature 相關的。雖然 git merge的時候會自動判斷是否使用fast-farward模式,但是有時候爲了更明確,我們還是要加參數–no-ff或者–ff。

2.2.2 Release 分支
release分支在我看來是 pre-master。release分支從 develop 分支 fork 出來,最終會合併到 develop分支和 master分支。合併到 master分支上就是可以發佈的代碼了。有人可能會問那爲什麼合併回 develop分支呢?很簡單,有了 release分支,那麼相關的代碼修復就只會在 release分支上改動了,最後必然要合併到 develop分支。下面細說。

我們最初所有的開發工作都在 develop分支上,當我們這一期的功能開發完畢的時候,我們基於 develop分支開一個新的release分支。這個時候我們就可以對 release分支做統一的測試了,另外做一些發佈準備工作:比如版本號之類的。

如果測試工作或者發佈準備工作和具體的開發工作由不同人來做,比如國內的 RD 和 QA,這個 RD 就可以繼續基於develop分支繼續開發了。再或者說公司對於發佈有嚴格的時間控制,開發工作提前並且完美的完成了,這個時候我們就可以在develop 分支上繼續我們下一期的開發了。同時如果測試有問題的話,我們將直接在release分支上修改,然後將修改合併到develop分支上。

待所有的測試和準備工作做完之後,我們就可以將 release分支合併到master 分支上,並進行發佈了。

一些相關命令如下。
新建 release 分支

$ git checkout -b release-1.2 develop
Switched to a new branch "release-1.2"
$ ./bump-version.sh 1.2
File modified successfully, version bumped to 1.2.
$ git commit -a -m "Bumped version number to 1.2"
[release-1.2 74d9424] Bumped version number to 1.2
1 files changed, 1 insertions(+), 1 deletions(-)

2.2.2.1 release 分支合併到 master 分支
$ git checkout master
Switched to branch ‘master’
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2
2.2.2.2 release 分支合併到 develop 分支
$ git checkout develop
Switched to branch ‘develop’
$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)
2.2.2.3 最後,刪除 release 分支
$ git branch -d release-1.2
Deleted branch release-1.2 (was ff452fe).
2.2.3 Hotfix 分支
顧名思義,hotfix分支用來修復線上 bug。當線上代碼出現 bug 時,我們基於 master分支開一個 hotfix分支,修復 bug 之後再將 hotfix分支合併到master分支並進行發佈,同時 develop分支作爲最新最全的代碼分支,hotfix分支也需要合併到 develop分支上去。仔細想一想,其實 hotfix分支和 release分支功能類似。hotfix的好處是不打斷develop 分支正常進行,同時對於生產代碼的修復貌似也沒有更好的方法了(總不能直接修改 master代碼吧)。
在這裏插入圖片描述
一些相關的命令。
2.2.3.1 新建 hotfix 分支

$ git checkout -b hotfix-1.2.1 master
Switched to a new branch "hotfix-1.2.1"
$ ./bump-version.sh 1.2.1
Files modified successfully, version bumped to 1.2.1.
$ git commit -a -m "Bumped version number to 1.2.1"
[hotfix-1.2.1 41e61bb] Bumped version number to 1.2.1
1 files changed, 1 insertions(+), 1 deletions(-)

2.2.3.2 Fix bug

$ git commit -m "Fixed severe production problem"
[hotfix-1.2.1 abbe5d6] Fixed severe production problem
5 files changed, 32 insertions(+), 17 deletions(-)
2.2.3.3 buffix 之後,hotfix 合併到 master
$ git checkout master
Switched to branch 'master'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)
$ git tag -a 1.2.1

2.2.3.4 hotfix 合併到 develop 分支

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff hotfix-1.2.1
Merge made by recursive.
(Summary of changes)

2.2.3.5 刪除 hotfix 分支

$ git branch -d hotfix-1.2.1
Deleted branch hotfix-1.2.1 (was abbe5d6).

三、Git 分支管理和衝突解決
3.1 合併分支間的修改 Merge
合併操作將兩條或多條分支合併到一起,實際上有好幾種分支合併方法,下面介紹主要的三種:

3.1.1 直接合並(straight merge):
把兩條分支上的歷史軌跡合併,交匯到一起。比如要把dev分支上的所有東東合併到master分支:

首先先到master分支:git checkout master
然後把dev給合並過來:git merge dev
注意沒參數的情況下merge是fast-forward的,即Git將master分支的指針直接移到dev的最前方。
換句話說,如果順着一個分支走下去可以到達另一個分支的話,那麼Git在合併兩者時,只會簡單移動指針,所以這種合併成爲快進式(Fast-forward)。
3.1.2 壓合合並(squashed commits):
將一條分支上的若干個提交條目壓合成一個提交條目,提交到另一條分支的末梢。

把dev分支上的所有提交壓合成主分支上的一個提交,即壓合提交:

$ git checkout master
$ git merge --squash dev

此時,dev上的所有提交已經合併到當前工作區並暫存,但還沒有作爲一個提交,可以像其他提交一樣,把這個改動提交到版本庫中:

$ git commit –m “something from dev”

3.1.3 揀選合併(cherry-picking):
揀選另一條分支上的某個提交條目的改動帶到當前分支上。每一次提交都會產生一個全局唯一的提交名稱,利用這個名稱就可以進行揀選提交。
比如在dev上的某個提交叫:321d76f
把它合併到master中:

$ git checkout master
$ git cherry-pick 321d76f

要揀選多個提交,可以給git cherry-pick命令傳遞-n選項,比如:

$ git cherry-pick –n 321d76f

這樣在揀選了這個改動之後,進行暫存而不立即提交,接着可以進行下一個揀選操作,一旦揀選完需要的各個提交,就可以一併提交。

3.2 衝突處理
當兩條分支對同一個文件的同一個文本塊進行了不同的修改,並試圖合併時,Git不能自動合併的,稱之爲衝突(conflict)。解決衝突需要人工處理。
比如當前在master分支,想把dev分支merge過來,結果產生了一個衝突,打開文件內容可以看到這麼一個衝突:

<<<<<<< HEAD

test in master

=======

test in dev

>>>>>>> dev

<<<<<<<標記衝突開始,後面跟的是當前分支中的內容。
HEAD指向當前分支末梢的提交。
=======之後,>>>>>>>之前是要merge過來的另一條分支上的代碼。

之後的dev是該分支的名字。
對於簡單的合併,手工編輯,然後去掉這些標記,最後像往常的提交一樣先add再commit即可。

3.3 刪除分支
有些分支沒有必要長期保存,比如分支中的代碼已經打了標籤並已發佈,或者實驗分支已經成功完成工作或中途廢棄等等。

注意:打了標籤的分支,Git在刪除該分支時,從版本樹起始到此標籤間的全部歷史軌跡均會保留,此時刪除分支操作只是刪除分支本身的名稱,因此可以說該分支沒有必要長期保存。

而在其他版本控制工具中,刪除分支通常意味着刪除分支上的所有歷史軌跡,所以不能因爲打了標籤就認爲其沒有必要保存。

刪除一個分支dev2:

$ git branch –d dev2

注意不能刪除當前所在分支,需要轉到別的分支上。
如果要刪除的分支已經成功合併到當前分支,刪除分支的操作會直接成功。
如果要刪除的分支沒有合併到當前所在分支,則會出現提示,如果確定無須合併而要直接刪除,則執行命令:

$ git branch –D dev2

進行強刪。

四、Git 版本回退
在版本迭代開發過程中,相信很多人都會有過錯誤提交的時候。這種情況下,菜鳥程序員可能就會虎驅一震,緊張得不知所措。而資深程序員就會微微一笑,摸一摸鋥亮的腦門,然後默默的進行版本回退。

對於版本的回退,我們經常會用到兩個命令:

$ git reset
$ git revert

那這兩個命令有何區別呢?先不急,我們後文詳細介紹。

4.1 git reset
假如我們的系統現在有如下幾個提交:
在這裏插入圖片描述

錯誤提交.png
其中:A 和 B 是正常提交,而 C 和 D 是錯誤提交。現在,我們想把 C 和 D 回退掉。而此時,HEAD 指針指向 D 提交(5lk4er)。我們只需將 HEAD 指針移動到 B 提交(a0fvf8),就可以達到目的。

只要有 git 基礎的朋友,一定會想到 git reset 命令。完整命令如下:

$ git reset --hard a0fvf8

命令運行之後,HEAD 指針就會移動到 B 提交下,如下圖示:
reset以後效果.png

而這個時候,遠程倉庫的 HEAD 指針依然不變,仍在 D 提交上。所以,如果直接使用git push命令的話,將無法將更改推到遠程倉庫。此時,只能使用-f 選項將提交強制推到遠程倉庫:

$ git push -f

採用這種方式回退代碼的弊端顯而易見,那就是會使 HEAD 指針往回移動,從而會失去之後的提交信息。將來如果突然發現,C 和 D 是多麼絕妙的想法,可它們已經早就消失在歷史的長河裏了。

而且,有些公司明令禁止使用 git reset命令去回退代碼,原因與上述一樣。所以,我們需要找到一個命令,既可以回退代碼,又可以保存錯誤的提交。這時,git revert命令就派上用場了。

4.2 git revert
git revert的作用通過反做創建一個新的版本,這個版本的內容與我們要回退到的目標版本一樣,但是HEAD指針是指向這個新生成的版本,而不是目標版本。

使用 git revert命令來實現上述例子的話,我們可以這樣做:先 revert D,再 revert C (有多個提交需要回退的話需要由新到舊進行 revert):

$ git revert 5lk4er
$ git revert 76sdeb

在這裏插入圖片描述
反向創建版本回退.png
這裏只有兩個提交需要 revert,我們可以一個個回退。但如果有幾十個呢?一個個回退肯定效率太低而且容易出錯。我們可以使用以下方法進行批量回退:

$ git revert OLDER_COMMIT^..NEWER_COMMIT

這時,錯誤的提交 C 和 D 依然保留,將來進行甩鍋的時候也有依可循。而且,這樣操作的話 HEAD 指針是往後移動的,可以直接使用 git push命令推送到遠程倉庫裏。而這種做法,正是企業所鼓勵的。

我們再舉個更難一點的例子。

假如現在有三個提交,但很不巧的是,那個錯誤的提交剛好位於中間。如下圖示:
在這裏插入圖片描述

位於中間的錯誤提交.png
這時,直接使用 git reset命令將 HEAD 指針重置到 A 提交顯然是不行的,因爲 C 提交是正確的,需要保留的。先把 C 提交 及 B 提交全部回退,再使用 cherry-pick 命令將 C 提交重新再生成一個新的提交 C’’,這樣就實現了將 B提交回退的需求。完整的過程如下:
在這裏插入圖片描述
1.png

通過以上對比可以發現,git reset與 git revert最大的差別就在於,git reset會失去後面的提交,而git revert是通過反做的方式重新創建一個新的提交,而保留原有的提交。在企業裏,應儘量使用 git revert命令,能不用 git reset命令儘量不用。
五、命名規範
5.1 主版本.次版本.修訂號
1.0.0

版本號主要有3部分構成(由兩個.分割成三部分)主版本、次版本、修訂號:
主版本:程序的主版本號,除非系統做整體重構,一般不變化
次版本:功能版本號,一般爲功能迭代的版本號,每次版本號爲上一次正常按迭代計劃發版的次版本 + 1;主版本發生變更,次版本需重置爲0
比如:上次按正常按迭代計劃發版的版本號爲v1.9.0,本次版本號爲 v1.(9+1).0,即 v1.10.0
修訂號:每次線上BUG修復,該版本號相對上次修訂號+1 (前提:相同主版本以及次版本);主版本和次版本發生變更,修訂號需重置爲0
比如:上次修訂號爲v1.9.3,本次版本號爲 v1.9.(3+1),即 v1.9.4

5.2 分支命名規範
5.2.1 主分支:
master:master 分支就叫 master 分支
develop:develop 分支就叫 develop 分支

5.2.2 輔助分支:
5.2.2.1 Feature 分支
feature/v1.16.0_xxx
feature/v1.16.0_yyy
feature/v1.16.0_zzz

v1.16.0 表示當前迭代的版本號,xxx、yyy、zzz 表示當前迭代的功能或業務單元的名稱

5.2.2.2 Release 分支
release/v1.17.0
release/v1.18.0

v1.17.0、v1.18.0 根據上線需求和系統上線計劃,合理規劃版本號,每個大版本號表示一次上線正常上線過程。

5.2.2.3 Hotfix 分支
hotfix/v1.17.1
hotfix/v1.17.2

v1.17.1、v1.17.2 表示v1.17.0 這個版本做了2次線上問題熱修復。

六、總結
並行開發:依據迭代的發版計劃和任務分解,創建feature(不同迭代需通過版本號隔離,同一個迭代內要上線的功能需要通過feature隔離)

保持迭代內代碼的可預見性&可控制性:
迭代內,只允許主迭代的feature代碼提交到develop分支

哪裏有問題改哪裏,改完後及時合併到主分支:
release(fit)環境的問題修復:應從release分支拉出分支進行問題修復,修復後及時合併到develop主分支
master環境的問題修復:應從生產環境對應的tag(一般爲最新的版本號)拉出分支進行問題修復,問題修復後及時合併代碼至develop主分支和master主分支

作者:耐得千事煩
鏈接:https://www.jianshu.com/p/92305d949c0e
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

作者:耐得千事煩
鏈接:https://www.jianshu.com/p/92305d949c0e
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章