如何避免Git合并远程分支时出现可读性差的日志

问题及现象

当某一分支(假设为main)的本地仓库和远程仓库都基于同一个提交进行了修改,并分别创建了新的提交时,在本地执行git push origin main会提示先要执行git pull合并远程代码。
本地和远程仓库基于同一个提交进行了修改
如下示例:

# 本地修改与远程仓库不一致时,推送代码到远程仓库时提示先要执行git pull操作
$ git push origin main
warning: redirecting to https://gitlab.com/zhangsan/testversion.git/
To http://gitlab.com/zhangsan/testversion.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'http://gitlab.com/zhangsan/testversion.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

如果此时我们按照提示信息执行:git pull origin main,可能会发生2件事情:
(1)代码冲突,这个不一定会出现,如果本地修改跟远程仓库中的修改不在一个文件中,就不会出现冲突
(2)在本地解决冲突(如果存在)后提交时会出现一个“Merge branch ...”的日志,看起来不友好,可读性非常差,同时分支的历史看起来也很乱

操作详情如下:

$ git pull origin main
warning: redirecting to https://gitlab.com/zhangsan/testversion.git/
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 307 bytes | 23.00 KiB/s, done.
From http://gitlab.com/zhangsan/testversion
 * branch            main       -> FETCH_HEAD
   f2576b1..4dc87e6  main       -> origin/main
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

显然,出现了冲突,解决冲突并提交最新修改。

$ git commit -a
# 解决冲突后执行“git commit -a”时默认会生成一个“Merge branch...”日志,看起来并不友好
Merge branch 'main' of http://gitlab.com/zhangsan/testversion into main

# Conflicts:
#       index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please run
#       git update-ref -d MERGE_HEAD
# and try again.


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Your branch and 'origin/main' have diverged,

# 提交后查看日志,这样的日志不友好,而且显得很乱
$ git log --oneline
ea5ceab (HEAD -> main) Merge branch 'main' of http://gitlab.com/zhangsan/testversion into main

分支历史看起来也有点乱:
Git_Pull时分支历史看起来乱

原因分析及解决办法

之所以存在本地执行git push时提示需要先执行git pull合并远程代码,是因为在本地和远程分别基于一个相同的提交进行了修改,这与基于某个相同的提交创建2个新分支进行修改是一个道理。
实际上这种情况在实际开发中会经常遇到,比如:在开发新的功能时通常都是基于当前master最新的提交拉出一个新的分支进行修改并提交。假如张三和李四需要同时开发2个不同的需求,那么张三和李四都会基于master拉出新的开发分支进行修改,如果张三先开发并测试完毕就会将代码推送到远程master,等李四开发并测试需要推送到远程master时,执行git push操作一定会提示先要执行git pull拉取远程最新的代码进行合并。

为了避免出现合并日志不友好和分支历史不整洁的问题,在执行git pull时使用-r选项,即:git pull origin main -r,或者:git pull origin main --rebase
执行git pull origin main -r时与在本地执行git rebase的效果是一样的,解决好冲突之后需要执行git rebase --continue,这样就可以保持提交日志的可读性,也可以使得分支历史干净。

# 本地修改与远程不一致时执行“git pull origin main -r”提示存在冲突
$ git pull origin main -r
warning: redirecting to https://gitlab.com/zhangsan/testversion.git/
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 272 bytes | 10.00 KiB/s, done.
From http://gitlab.com/zhangsan/testversion
 * branch            main       -> FETCH_HEAD
   ea5ceab..6b252fe  main       -> origin/main
error: could not apply 90f947e... fix: add div13
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 90f947e... fix: add div13
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html

手动解决冲突之后,先要执行git add命令添加修改过的文件,再次实行git rebase --continue合并冲突,此时不在会出现“Merge branch ...”这样的不友好日志。

$ git rebase --continue
fix: add div13

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto 6b252fe
# Last command done (1 command done):
#    pick 90f947e fix: add div13
# No commands remaining.
# You are currently rebasing branch 'main' on '6b252fe'.
#
# Changes to be committed:
#       modified:   index.html

Successfully rebased and updated refs/heads/main.

此时再来看分支历史也非常简洁:
Git_Pull_Rebase分支历史整洁

使用总结

1.尽快合并远程最新代码,为了确保这一点每次在本地修改之前都先执行一次git pull操作。
假设在本地分支b1上开发一个新的功能,尽快将远程master分支的代码拉取到本地并与本地b1分支做rebase操作,操作顺序可以总结为:

git checkout master
git pull origin master
git checkout b1
git rebase master

2.合并相同分支的远程代码时使用“-r”选项(git pull origin 分支名称 -r),保持提交日志的可读性和分支历史的简洁性。
3.git pull不带-r选项时本质上是:git fetch + git merge,带上-r选项时为:git fetch + git rebase

【参考】
https://www.qikegu.com/docs/4381 Git – 拉取(git pull)时的冲突

posted @ 2022-07-20 20:23  nuccch  阅读(566)  评论(0编辑  收藏  举报