引言
當(dāng)我們做好了一個(gè)新功能或者修復(fù)了一個(gè)bug之后怎么把它應(yīng)用到主分支上呢?這就需要代碼進(jìn)行代碼合并了。
這里研究merge合并方式。
一、merge合并代碼
我初始化一個(gè)git倉庫 test_merge;然后進(jìn)入test_merge文件夾;然后新建文件a.txt;然后進(jìn)行add、commit;
[root@localhost GitTest]# git init test_merge
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /root/GitTest/test_merge/.git/
[root@localhost GitTest]# touch a.txt
[root@localhost GitTest]# git add ./
fatal: not a git repository (or any of the parent directories): .git
[root@localhost GitTest]# ls
a.txt test1 test2 test_merge
[root@localhost GitTest]# rm -rf a.txt
[root@localhost GitTest]# rm -rf test_merge/
[root@localhost GitTest]# ls
test1 test2
[root@localhost GitTest]#
[root@localhost GitTest]#
[root@localhost GitTest]# git init test_merge
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /root/GitTest/test_merge/.git/
[root@localhost GitTest]# cd test_merge/
[root@localhost test_merge]# touch a.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "init add a.txt"
[master (root-commit) f312f7a] init add a.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a.txt
[root@localhost test_merge]#
然后查看日志:git log
[root@localhost test_merge]# git log
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df (HEAD -> master)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
可以看到我們已經(jīng)創(chuàng)建了文件a.txt并提交到了本地倉庫;
然后新建分支feature_login;并切換到分支feature_login;并新建文件login.java;然后進(jìn)行add、commit;
[root@localhost test_merge]# git checkout -b feature_login
Switched to a new branch 'feature_login'
[root@localhost test_merge]# touch login.java
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "feature login"
[feature_login 3f75297] feature login
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 login.java
至此我們的登錄模塊就開發(fā)完成了,查看日志,可以看到已經(jīng)提交到本地倉庫了,并且HEAD已經(jīng)指向:
[root@localhost test_merge]# git log
commit 3f75297804d72b6cbd5c3480b1961dc96b049fe2 (HEAD -> feature_login)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:58:59 2023 +0800
feature login
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df (master)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
然后我們要把新開發(fā)好的登錄模塊合并到master(假如它是線上分支)分支上去;
我切換到master分支上:git checkout master
然后執(zhí)行合并:git merge feature_login
[root@localhost test_merge]# git checkout master
Switched to branch 'master'
[root@localhost test_merge]# git log
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df (HEAD -> master)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
[root@localhost test_merge]# git merge feature_login
Updating f312f7a..3f75297
Fast-forward
login.java | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 login.java
可以看到merge成功了,使用的是Fast-forward方式合并的,這個(gè)我們待會(huì)兒說。然后查看日志會(huì)發(fā)現(xiàn)HEAD已經(jīng)指向master、feature_login;
[root@localhost test_merge]# git log
commit 3f75297804d72b6cbd5c3480b1961dc96b049fe2 (HEAD -> master, feature_login)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:58:59 2023 +0800
feature login
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
二、Fast-forward模式
剛才我們合并的時(shí)候已經(jīng)看到了,我們執(zhí)行git merge
的時(shí)候合并完成后提示我們是Fast-forward模式,我們沒有指定呀~這個(gè)是哪里來的呢,其實(shí)我們執(zhí)行合并的時(shí)候git幫我們自動(dòng)選擇了合并模式;這個(gè)模式就是Fast-forward模式。當(dāng)我們將feature_login合并到master的時(shí)候git發(fā)現(xiàn)master的當(dāng)前節(jié)點(diǎn)和feature_login的根節(jié)點(diǎn)相同;那么git將master的頭指針快速移動(dòng)到feature_login的位置;所以faster-forward不會(huì)發(fā)生真正的合并;只是通過移動(dòng)指針造成合并的假象而已。
詳細(xì)如圖,可以看到合并前feature_login分支的頭指針指向feature_login,而master分支的頭指針是指向master的:
我們執(zhí)行了merge后HEAD指向了master、feature_login;其實(shí)git就是將master的頭指針指向了feature_login;
通常功能分支(feature、fix) 合并到master 后會(huì)被刪除,而通過 Fast-forward 模式產(chǎn)生的合并可以產(chǎn)生干凈并且線性的歷史記錄;看起來就像一條直線一樣~舒服。
三、non-Fast-forward模式
剛才了解了Fast-forward模式,而這個(gè)模式恰恰跟它相反;比如還在上述場(chǎng)景中:當(dāng)git執(zhí)行合并的時(shí)候發(fā)現(xiàn)master已經(jīng)比feature_login快了幾個(gè)版本的時(shí)候,這時(shí)候git就沒辦法自動(dòng)幫我們進(jìn)行Fast-forward合并了,這種情況不能通過僅僅移動(dòng)頭指針就完成合并操作;這時(shí)候git就得做出正真的合并操作了,具體動(dòng)作大概像這樣:
①找出master和feature_login的公共祖先節(jié)點(diǎn);(注意此時(shí)可能會(huì)有沖突)
②創(chuàng)建新的節(jié)點(diǎn)(m),將其余的差異合并到新節(jié)點(diǎn),并進(jìn)行commit
③將master、feature_login的頭指針移動(dòng)到新節(jié)點(diǎn)(m)
接下來模擬這個(gè)操作:
1、我先在master分支上進(jìn)行兩次提交;
①查看master當(dāng)前日志
②新建文件b.txt;并add、commit;新建文件c.txt;執(zhí)行add、commit;
[root@localhost test_merge]# touch b.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "add b.txt"
[master 801883d] add b.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
[root@localhost test_merge]# touch c.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "add c.txt"
[master dcf5456] add c.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c.txt
③查看日志,可以看到現(xiàn)在版本在add c.txt的版本
2、然后切回feature_login分支,新建文件d.txt;進(jìn)行add、commit;此時(shí)master分支是比feature分支快一個(gè)版本的;
①切換到feature_login分支,查看日志;可以看到只有兩次提交
②新建文件d.txt;進(jìn)行add、commit;
[root@localhost test_merge]# touch d.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "add d.txt"
[feature_login e8e9f61] add d.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d.txt
③查看日志,可以看到三次提交,feature_login分支的HEAD目前是在add d.txt版本上
3、我切回master分支進(jìn)行merge操作
①切回master分支,查看日志;可以看到master的HEAD還在add c.txt版本上;此時(shí)master分支是比feature_login分支快一個(gè)版本
[root@localhost test_merge]# git checkout master
Switched to branch 'master'
[root@localhost test_merge]# git log
commit dcf545620fb4707c45fe254dd1de7ae4c5d0c9be (HEAD -> master)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:04:35 2023 +0800
add c.txt
commit 801883d6330a3ff4537c5cea06b6a35006ac5669
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:04:07 2023 +0800
add b.txt
commit 3f75297804d72b6cbd5c3480b1961dc96b049fe2
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:58:59 2023 +0800
feature login
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
②執(zhí)行merge操作:git merge feature_login
可以看到如圖打開了交互窗口,需要我們輸入上文提到得到新版本的commit的message消息:
②我不動(dòng)默認(rèn)生成的“Merge branch ‘feature_login’”;在下面一行輸入新的commit消息:“這是no-Fast-forward模式”;記得將交互框切換成insert模式哦;然后保存退出;看到這樣就是成功了~~這個(gè)是no-Fast-forward模式的哦
[root@localhost test_merge]# git merge feature_login
hint: Waiting for your editor to close the file... 7L, 284C written
Merge made by the 'ort' strategy.
d.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 d.txt
③然后我們來看一下日志
神奇~~
四、squash模式
此模式可以對(duì)一些多余的commit進(jìn)行壓縮;這個(gè)對(duì)于粗心的我和有個(gè)有想法很多的Leader的人都很食用~~
場(chǎng)景一:我寫完了代碼進(jìn)行了提交,然后發(fā)現(xiàn)有個(gè)字母忘記改成大寫了,然后改好又做了提交;然后又發(fā)現(xiàn)還有個(gè)字母沒改成小寫,改好后又進(jìn)行了提交…很多,這要是能合在一起就好了
場(chǎng)景二:剛把代碼寫好提交了,leader說第三行的日志格式改一下,我不喜歡;然后改了提交了;然后又說給客戶的提示要小寫;又改又提交…又又又改,又又又提交;亂的自己都看不下去了吧;
好了squash來了,可以將這些又又又合并成一個(gè)commit;優(yōu)雅,示例:
我切換到feature_login分支上新建三個(gè)文件x.txt、y.txt、z.txt;并且分別進(jìn)行add、commit;
[root@localhost test_merge]# git checkout feature_login
Switched to branch 'feature_login'
[root@localhost test_merge]# git log
commit e8e9f61ac360bb29fa1201039ef1920bc4a41c7e (HEAD -> feature_login)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:08:43 2023 +0800
add d.txt
commit 3f75297804d72b6cbd5c3480b1961dc96b049fe2
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:58:59 2023 +0800
feature login
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
[root@localhost test_merge]# touch x.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "add x.txt"
[feature_login b48e7de] add x.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 x.txt
[root@localhost test_merge]# touch y.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "add y.txt"
[feature_login 1c5a213] add y.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 y.txt
[root@localhost test_merge]# touch z.txt
[root@localhost test_merge]# git add .
[root@localhost test_merge]# git commit -m "add z.txt"
[feature_login a177755] add z.txt
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 z.txt
[root@localhost test_merge]# git log
commit a17775559ed87a63025728b144ff7f573f3f61f1 (HEAD -> feature_login)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:38:24 2023 +0800
add z.txt
commit 1c5a2130ff4c767ddb243d63ccc559edc5b0114e
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:37:59 2023 +0800
add y.txt
commit b48e7de3c6633cdc4f53e48a14da23fb285cbd67
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:37:32 2023 +0800
add x.txt
commit e8e9f61ac360bb29fa1201039ef1920bc4a41c7e
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:08:43 2023 +0800
add d.txt
commit 3f75297804d72b6cbd5c3480b1961dc96b049fe2
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:58:59 2023 +0800
feature login
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
然后切回master分支,進(jìn)行squash合并,將feature_login的多個(gè)提交壓縮成一個(gè),合并到master上
[root@localhost test_merge]# git checkout master
Switched to branch 'master'
[root@localhost test_merge]# git merge --squash feature_login
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
此時(shí)查看git狀態(tài),會(huì)發(fā)現(xiàn)已經(jīng)將剛才feature_login的改動(dòng)帶過來了
[root@localhost test_merge]# git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: x.txt
new file: y.txt
new file: z.txt
然后我們手動(dòng)進(jìn)行提交即可,可以看到此時(shí)已經(jīng)實(shí)現(xiàn)將feature_login上的三個(gè)提交壓縮成一個(gè)合并到master上了
[root@localhost test_merge]# git commit -m "merge squash form feature_login to master"
[master 0cf65a1] merge squash form feature_login to master
Committer: root <root@localhost.localdomain>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:
git config --global --edit
After doing this, you may fix the identity used for this commit with:
git commit --amend --reset-author
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 x.txt
create mode 100644 y.txt
create mode 100644 z.txt
[root@localhost test_merge]# git log
commit 0cf65a159e6e9173fa0ca630d17e2dac6f50f957 (HEAD -> master)
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:48:37 2023 +0800
merge squash form feature_login to master
commit 9f6c1886b29b742728f36000744ca487f6089ecc
Merge: dcf5456 e8e9f61
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:12:27 2023 +0800
Merge branch 'feature_login'
這是no-Fast-forward模式
commit e8e9f61ac360bb29fa1201039ef1920bc4a41c7e
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:08:43 2023 +0800
add d.txt
commit dcf545620fb4707c45fe254dd1de7ae4c5d0c9be
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:04:35 2023 +0800
add c.txt
commit 801883d6330a3ff4537c5cea06b6a35006ac5669
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 16:04:07 2023 +0800
add b.txt
commit 3f75297804d72b6cbd5c3480b1961dc96b049fe2
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:58:59 2023 +0800
feature login
commit f312f7a5e736abc3d581ee0d9db5b8b3cd3b89df
Author: root <root@localhost.localdomain>
Date: Fri Sep 1 14:40:16 2023 +0800
init add a.txt
絲滑~
五、指定合并模式以及其余參數(shù)
指定Fast-forward:git merge --ff XXX
指定no-Fast-forward:gir merge --no-ff XXX
squash操作:git merge --squash XXX
其余各指令的官方解釋:文章來源:http://www.zghlxwxcb.cn/news/detail-716168.html
usage: git merge [<options>] [<commit>...]
or: git merge --abort
or: git merge --continue
-n do not show a diffstat at the end of the merge
--stat show a diffstat at the end of the merge
--summary (synonym to --stat)
--log[=<n>] add (at most <n>) entries from shortlog to merge commit message
--squash create a single commit instead of doing a merge
--commit perform a commit if the merge succeeds (default)
-e, --edit edit message before committing
--cleanup <mode> how to strip spaces and #comments from message
--ff allow fast-forward (default)
--ff-only abort if fast-forward is not possible
--rerere-autoupdate update the index with reused conflict resolution if possible
--verify-signatures verify that the named commit has a valid GPG signature
-s, --strategy <strategy>
merge strategy to use
-X, --strategy-option <option=value>
option for selected merge strategy
-m, --message <message>
merge commit message (for a non-fast-forward merge)
-F, --file <path> read message from file
--into-name <name> use <name> instead of the real target
-v, --verbose be more verbose
-q, --quiet be more quiet
--abort abort the current in-progress merge
--quit --abort but leave index and working tree alone
--continue continue the current in-progress merge
--allow-unrelated-histories
allow merging unrelated histories
--progress force progress reporting
-S, --gpg-sign[=<key-id>]
GPG sign commit
--autostash automatically stash/stash pop before and after
--overwrite-ignore update ignored files (default)
--signoff add a Signed-off-by trailer
--no-verify bypass pre-merge-commit and commit-msg hooks
六、怎么選擇使用哪種模式的建議
如果我們追求干凈線性 git 歷史記錄,那么我可以使用 git merge --ff-only
方式保持主線模式開發(fā)是一種不錯(cuò)的選擇
如果我們不追求線性的 git 歷史記錄,要體現(xiàn)相對(duì)真實(shí)的 merge 記錄,那么默認(rèn)的 git merge --ff
比較合適
如果我們要嚴(yán)格監(jiān)控每個(gè)功能分支的合并情況,那么使用 git merge --no-ff
禁用 Fast-forward 是一個(gè)不錯(cuò)的選擇文章來源地址http://www.zghlxwxcb.cn/news/detail-716168.html
到了這里,關(guān)于Git的merge合并代碼詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!