产生于git pull的奇怪提交记录Merge branch br2 of gitlabel.xx.com:xiaobai/test into br2

问题

在使用git进行git push操作的时候,往往会发现这样的提示。

 ! [rejected]        br2 -> br2 (fetch first)
error: failed to push some refs to 'git@git.xxx.com:daihaoxin/test.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拉取一下远程代码。然后我遇到了这个提示。
在这里插入图片描述

在这里直接进行保存,然后提交,就会发现commit日志中,会出现一条新的log记录。这个记录本身没有问题,只是这种毫无意义,如果能避免这种问题,岂不是更好。下面就来了解下为什么会出现这样的提交记录,怎么来避免它?

复现

github上创建一个名为test的仓库,做为复现问题的演示。

# clone 两次分别放到两个不同的文件夹中,用来代表不同用户的提交
git clone https://github.com/daihaoxin/test test1
git clone https://github.com/daihaoxin/test test2

操作一

test1 没有修改,test2 修改后提交,然后 test1 去更新。

# test2 修改操作
cd ../test2
touch test2.js
git add test2.js 
git commit -m "add file test2.js"
git push
# 看下提交历史
git log
# commit 06997730b90a18e3cf7aa0e7cdf4f799f082b42c
# 
# add file test2.js
# 
# commit 84c125f932c37c722c878c312fe2d7b8ecdf94cf
# 
# Initial commit

# 进入 test1
cd ../test1
# 查看test1的log
git log
# commit 84c125f932c37c722c878c312fe2d7b8ecdf94cf
# 
# Initial commit

# 进行拉取
git pull
# ...
# From https://github.com/daihaoxin/test
# 84c125f..0699773  master     -> origin/master
# Updating 84c125f..0699773
# Fast-forward
# test2.js | 0
# 1 file changed, 0 insertions(+), 0 deletions(-)
# create mode 100644 test2.js
git log
# commit 06997730b90a18e3cf7aa0e7cdf4f799f082b42c
# 
#      add file test2.js
# 
# commit 84c125f932c37c722c878c312fe2d7b8ecdf94cf
# 
#      Initial commit

很好,完美,符合预期。

操作二

  1. test1进行本地修改
  2. test1提交修改内容并push到远端
  3. test2进行本地修改
  4. test2不提交修改内容,只从远端更新test1的提交的内容

test1 的操作

touch test1.js
git add test1.js 
git commit -m "test1 add file test1.js"
git push
git log
# commit 07bb18d2f0169ad31dad20189f136ab1faffea37
# 
#     test1 add file test1.js
# 
# commit 06997730b90a18e3cf7aa0e7cdf4f799f082b42c
# 
#     add file test2.js
# 
# commit 84c125f932c37c722c878c312fe2d7b8ecdf94cf
# 
#     Initial commit

test2 的操作。

cd ../test2
echo "修改test2.js" > test2.js
cat test2.js
# 修改test2.js
git pull
# ...
#     From https://github.com/daihaoxin/test
#     0699773..07bb18d  master     -> origin/master
#     Updating 0699773..07bb18d
#     Fast-forward
#     test1.js | 1 +
#     1 file changed, 1 insertion(+)
#     create mode 100644 test1.js

这里有两个刻意的点:

  1. 两边修改的内容是不重贴的,避免出现冲突,因为冲突不是关注的点
  2. 没有git stash ,直接进行了更新,测试一下是否因为没有git stash而造成的弹出提示

看起来没有问题。

操作三

  1. test1进行本地修改
  2. test1提交修改内容并push到远端
  3. test2将操作二中修改的内容提交,并push到远端

test1 的操作:

cd test1
echo "修改文件test1.js" > test1.js
cat test1.js
# 修改文件test1.js
git add test1.js
git commit -m "modified file test1.js"
git push
# ...
# Total 3 (delta 0), reused 0 (delta 0)
# To https://github.com/daihaoxin/test
# 07bb18d..ad85c1e  master -> master

test2 的操作,这里因为操作二中的修改还没有提交,所以直接提交就可以了。

cd test2
git st
# On branch master
# Your branch is up-to-date with 'origin/master'.
# 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:   test2.js
# 
# no changes added to commit (use "git add" and/or "git commit -a")
git add test2.js
git commit -m "modify file test2.js"
git push
# 因为远端已经有 test1 的提交了,所有这里 git 提醒需要先 git pull
# To https://github.com/daihaoxin/test
#   ! [rejected]        master -> master (fetch first)
# error: failed to push some refs to 'https://github.com/daihaoxin/test'
# 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
# 然后弹出如下的提示
#Merge branch 'master' of https://github.com/daihaoxin/test

# # Please enter a commit message to explain why this merge is necessary,
# # especially if it merges an updated upstream into a topic branch.
# #
# # Lines starting with '#' will be ignored, and an empty message aborts
# # the commit.

上面的操作重现了,本文开头遇到的情况,这里就进行保存之后,再看下提交记录。就出现了最上面毫无意义的一条(第三行)。

Merge: 5b2ded5 ad85c1e

Merge branch 'master' of https://github.com/daihaoxin/test

commit 5b2ded58a45e7cde82292ba6a71d768563fd8655

modify file test2.js

commit ad85c1e01e8fdaa27036099f244afcaddf6f36b4

modified file test1.js

commit 07bb18d2f0169ad31dad20189f136ab1faffea37

test1 add file test1.js

commit 06997730b90a18e3cf7aa0e7cdf4f799f082b42c

add file test2.js

commit 84c125f932c37c722c878c312fe2d7b8ecdf94cf

Initial commit

原理

上一节通过三种情况来使用git pull,只有在第三种的情况下,才会出现本文开头的问题,这里就让我们来了解下原因。

在git中,无论是 pull、push 亦或是 merge 操作,其实背后都是有很多的不同的模式的。pull 的默认模式是fetch+merge 的一个过程,即先使用fetch从远端拉取新的更新,然后再 merge到本地分支中去。

操作一操作二,远端 分支超前于本地分支,并且本地分支没有未同步的 commit 记录时,pull操作则直接使用 fetch 从远端拉取代码,然后merge到本地分支,这时候的merge会采用 fast-forward 模式,这种模式下,并不会产生合并节点,也就是说不会产生多余的那条 log 信息。

注意看下操作二进行pull操作时的信息。
在这里插入图片描述

操作三,本地先 commit 后再去 pull,那么此时,远端分支和本地会分支会出现分叉,通过 pull 操作拉取更新时,先使用fetch从远端更新代码,然后merge到本地的时候,会使用recursive模式(一般称为Three-Way Merge三方合并),三方合并一定会产生新的合并节点和 log 信息。

下图是操作三中的日志信息。
在这里插入图片描述

两种模式的区别
在这里插入图片描述

解决办法

在执行git pull的时候加上–rebase参数。这个参数的意思是,fetch从远端拉取代码后,先使用rebase执行变基操作,成功后再进行merge。(如果有冲突需要手动解决)

<完结>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值