Git从入门到熟练第十三讲 git pull

前言:

上一讲我们讲了如何将本地修改提交给远程源文件资源,以及产生提交冲突的原因,如何将本地删除或新建的分支提交远程,如何提交tags的修改。这一讲我们将如何让本地资源与远程资源同步,同时分析git pull发生冲突的缘由和解决方案。

目录

课前准备:

13.1  git pull

13.2 git pull:由git fetch 和git merge组成的操作

13.2.1 git fetch

 13.2.2  git merge in git pull

13.3 git pull 冲突

13.3.1 clean merge

13.3.2  git pull中的合并冲突


课前准备:

虽然继续使用上一讲的git资源也可以,但是这边为了和书中一致,还是决定重新新建。

下载这个资源然后解压,运行文件make_math_repo.sh,在同一目录下会生成math文件夹,输入以下代码,

bash make_math_repo.sh
cd math
git checkout -f master                   //不保存任何修改切换分支
cd ..
git clone --bare math math.git          //创建裸仓库
git clone math.git math.carol
git clone math.git math.bill

13.1  git pull

首先我们可以先明确一点,git pull是git push的镜像操作,即git push是向远端资源提交我们本地的修改,而git pull是将远端的更新修改同步到本地,如下图

 我们可以先实践一下,

1、首先我们先在math.bill进行修改并提交本地同时提交给math.git(远端资源)

cd math.bill
echo "Small change" >> another_rename
git commit -a -m "Small change"
git push                                    //提交给远端服务器

2、这时我们进入math.carol,查看远端情况,结果如下图

 可以得知我们和远端没有同步(out of date),如果这时候我们进行提交会怎么样?

 虽然我们没有对math.carol进行任何修改,但是我们没有和远端同步,因此提交修改的操作被拒绝了。

这时候,我们只要在math.carol输入命令git pull就能解决问题。

13.2 git pull:由git fetch 和git merge组成的操作

git pull实际上是由git fetch 和git merge FETCH_HEAD这两个命令构成的操作,我们详细分析这两部分命令对本地资源的操作,从而能够更好的理解git pull有时候为什么会产生冲突。

13.2.1 git fetch

git fetch是git pull命令的第一步,这一命令实际上是从远程资源中重新获得文件并将之并入你的本地仓库。

实践如下

1、进入math.bill文件进行修改并分别提交给本地和远端

cd ../math.bill
echo "Tiny change" >> another_rename
git commit -a -m "Another tiny change"
git push

2、进入math.carol,首先查看分支(为了更直观,我们用gitk

为了显示全部分支情况,下图中橘色框内容选中

 最后显示如下图

 3、输入命令git fetch,结果如下图

 输入gitk命令,看看分支有哪些变化(不要忘记view框设置)

 通过上下两张图的比较,我们可以直观的知道,git fetch命令实际上是更新了remotes/origin/master的内容(增加了一个新的提交),而为了和远端同步,我们就需要merge。

 13.2.2  git merge in git pull

git pull的第二个步骤就是git merge FETCH_HEAD命令。

首先我们需要了解什么是FETCH_HEAD?这是你刚刚fetch操作的remote分支指针(如上图)。FETCH_HEAD指向你fetch的最新的remote-tracking分支提交,因此我们可以在本地对我们的HEAD指向的分支和FETCH_HEAD指向的分支进行合并操作。

tips:我们可以尝试证明一下这里FETCH_HEAD与remotes/origin/master是一样的

在math.carol文件下进行如下操作,我们可以看到两者的SHA1 ID是一致的

在merge前,我们通常会通过diff查看合并分支会对哪些文件产生什么影响,如下图

 最后,我们合并FETCH_HEAD分支。

上面的操作如下图

经过详细的分析,在这里我们是不是对git pull中两个命令git fetchgit merge FETCH_HEAD 有了比较多的了解?下一节我们介绍git pull产生冲突和解决冲突的方式。

13.3 git pull 冲突

上一小节是在极其简单情况下的git pull,因为当math.bill修改的时候,math.carol对资源没有进行任何修改,但实际上情况比这要复杂。

13.3.1 clean merge

首先理解一下什么是clean merge?这是指git能够自动解决的合并冲突。比如两个本地仓库同时对相同文件的相同行进行修改,那么git便能够自动解决这个不同,但是要注意,这个自动的合并结果往往会出乎意料,出现不是你想要的结果。

我们可以做如下实践测试一下,

1、进入math.bill进行修改并提交给远端

echo "Small change 2" >> another_rename
git commit -a -m "Small change 2 from bill"
git push

2、进入math.carol进行相同的修改

echo "Small change 2" >> another_rename
git commit -a -m "Small change 2 from carol"

这里我们先明确一点,两个仓库文件的修改是一样的,只是提交名称不一致。这个时候git pull会怎么样?这个时候git会进行自动合并并提交分支。

 通过图示我们能够更直观的理解这点

13.3.2  git pull中的合并冲突

在尝试上一小节后,我们让场景更复杂一些,两个仓库对同一文件进行不同的修改,在git pull后会发生什么?

1、先在math.carol上一小节修改git push 提交远端,并在math.bill输入git pull使两个仓库又处于同步的状态

2、对math.bill文件进行小小修改并提交远端

echo "JKL MNO PQR" >> another_rename
git commit -a -m "JKL part of alphabet"
git push

3、对math.carol中文件进行修改

echo "ABC DEF GHI" >> another_rename
git commit -a -m "ABC part of alphabet"

这个时候git pull会有什么结果?

 从上图中看到发生了合并冲突。输入gitk查看现在状态

 从上图我们可以分析,git pull操作的两个部分,第一部分git fetch是成功了的(从remotes/origin/master更新了math.bill最新提交),第二部分git merge发生了冲突,而这个冲突只能手动解决。

这里我们回忆之前合并冲突章节,可以通过直接在相应文件的修改,或者通过mergetool进行修改。

这里通过mergetool进行手动修改并保存

 然后提交修改git commit,结果如下图

 

总结:

git pull实际上是git设计者为了初学者设计的命令,而为了更安全稳定的使用git,推荐使用git fetch和git merge FETCH_HEAD 而不是简单的git pull。

这样你可以知道自己每一步骤对哪些文件会产生什么影响,而不会出现莫名其妙的结果。如果你在团队项目中,开始养成使用git fetch而不是git pull的习惯吧!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值