>[info] git pull
功能:抓取远程的新提交(并和本地版本库合并)。
你的小伙伴已经向`origin/dev`分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
~~~
$ git add hello.py
$ git commit -m "add coding: utf-8"
[dev bd6ae48] add coding: utf-8
1 file changed, 1 insertion(+)
$ git push origin dev
To git@github.com:michaelliao/learngit.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
~~~
推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用`git pull`把最新的提交从`origin/dev`抓下来,然后,在本地合并,解决冲突,再推送:
~~~
$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
fc38031..291bea8 dev -> origin/dev
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream dev origin/<branch>
~~~
`git pull`也失败了,原因是没有指定本地`dev`分支与远程`origin/dev`分支的链接,根据提示,设置`dev`和`origin/dev`的链接:
~~~
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
~~~
再`pull`:
~~~
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
~~~
这回`git pull`成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的解决冲突完全一样。解决后,提交,再`push`:
~~~
$ git commit -m "merge & fix hello.py"
[dev adca45d] merge & fix hello.py
$ git push origin dev
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 747 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
291bea8..adca45d dev -> dev
~~~
因此,多人协作的工作模式通常是这样:
首先,可以试图用`git push origin branch-name`推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用`git pull`试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用`git push origin branch-name`推送就能成功!
如果`git pull`提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令`git branch --set-upstream branch-name origin/branch-name`。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
小结
查看远程库信息,使用`git remote -v`;
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用`git push origin branch-name`,如果推送失败,先用`git pull`抓取远程的新提交;
在本地创建和远程分支对应的分支,使用`git checkout -b branch-name origin/branch-name`,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用`git branch --set-upstream branch-name origin/branch-name`;
从远程抓取分支,使用`git pull`,如果有冲突,要先处理冲突。
扩展知识:
>[info] git pull = git fetch + git merge
但是合并操作并不总是会成功,如果自动合并失败,会在暂存区对合并前后文件进行标识,工作区进入冲突解决状态,在冲突解决完成之前不能提交。Git支持多种图形工具帮助完成冲突解决,执行如下命令,即可自动调用已安装的冲突解决工具。
注意理解这里的“工作区进入冲突解决状态”哦。试想一下,如果当前工作现场还在干活货怎么样呢?
答:实际上有个合并的操作你也知道了,所以同理,跟合并的情况一样,如果有“合并”操作,那么进入冲突前必须完成本地工作区未完成的工作,否则就拉失败了。
实际上不论是合并,还是拉,这与工作区的关系就是,只要发生冲突,就必须要求工作区是干净的,否则就可以进入“解决冲突状态”(满足快速合并的不需要解决冲突)。
实际上,pull只要有本地没有,远程有的新提交,哪怕是没有冲突(当前落后),也会要求本地工作区是干净的。(因为这会重置工作区,所以要保证你当前进行的工作啊。)
但是如果,这次没有拉到任何的新提交,则没有任何事。
注意这里的一个小细节,git的一般任何操作都不需要网络,也就是如果你不主动获取远程版本库信息的话,在看状态时,它是不知道远程领先于本地(远程有新的提交还没有拉到本地来),或者本地领先于远程(本地有新的提交还没有同步到远程),但是上面我们pull失败后明显看到了远程领先于本地的信息,我们也知道pull实际是两步,也就是说虽然pull失败了,但是fetch这个动作是完成了,只是merge失败了而已。不信我们撤销修改(不撤销修改的话还会报错和pull一样),直接merge试下,哈哈,也完成了合并吧。(这些细节都是git的许多小聪明之一。)
上面说得太乱了,其实可以总结下,只要是涉及到会改变工作区的操作,都会检查工作区是否是干净的。
注意快速合并(快进式合并)有两种情况哦,“当前领先”和“当前落后”,前者不会改变工作区,只是移动指针到当前而已,所以不要求工作区是干净的;而后者会改变工作区,并移动指针到最新的提交,所以会要求工作区是干净的(没有为添加到暂存区的修改,暂存区是干净的)。(注意快速合并没有一个提交哦,所以有时看不出来是合并过哦)
上面有个地方讲错了,不是所有需要改变工作区都会检查工作区是否干净,应该是检测我们的修改是否与拉取的新的提交是否有冲突。比如拉取得提交里面变动了test文件,但是我们本地只是修改test文件,就不会提示错误,不会强制需要我们完成工作。
合并操作也是这样的哦,很灵活的。也就是说之前都说错了,不一定要求工作区是干净的才能合并,只要和新的不产生冲突就不会影响,合并后工作区还可以继续工作。(或者说只要未完成的工作区文件名单中有本次合并变化/冲突的文件,那么则需要解决当前未完成的工作区问题)
>[info] 总之情况很多,git很复杂,暂时没有时间去讨论所有的情况,我们唯一能做的就是遇到实际情况时根据命令提示去解决问题,现在没有时间去总结所有的情况。
所有的合并都是两个提交(对象)的合并。
什么时候需要解决冲突:
两次提交有共同的文件修改,且内容不同。
总之遇到问题时看提示解决。
### 注意
单纯的看这个可能会以为3的父节点是2,实际上3和2的父节点都是1,4是3和2合并的结果。
commits图
![](https://box.kancloud.cn/2f054101b7c99a55f4e153da60ae210e_917x757.jpg)
Network图
![](https://box.kancloud.cn/dce7d32f1f3b1c0c290fc219f32035b4_404x244.jpg)
* * * * *
Network图
![](https://box.kancloud.cn/02299cf8572d0dc3d4c04750ef92d057_611x434.png)
commit info图(第一个红框加载时:Loading branch information……)分支结构信息
![](https://box.kancloud.cn/14d73bd510a8b2600cd40b5331564d6e_1738x327.png)
还可以看到`dev merge master`提交有两个父节点。
点击一个之后,显示可以和master快速合并。
![](https://box.kancloud.cn/5405e62cf3772d3de248d81e7c6d56d5_1920x1051.jpg)
- 说明
- git配置
- git与github的关系
- 基础概念
- git命令
- git init
- git status
- git diff
- git log
- git reflog
- git add
- git commit
- git reset
- git checkout
- git rm
- git stash
- git remote
- git push
- git clone
- git branch
- git fetch
- git merge
- git rebase
- git pull
- git tag
- 建立版本库
- 分支合并
- 远程库别名
- Pull requests
- 扩展知识
- 功能文件
- 差异看法
- 注意细节
- github移动端
- git工作系统理解
- 仓库嵌套问题
- 仓库的使用问题
- 常用命令
- 学习资料
- 学习总结
- 示例文件
- README.md
- CONTRIBUTING.md
- .gitignore
- coding
- 大小写问题
- 如何贡献
- 使用账号密码clone
- git目录分析
- HEAD
- 代码部署问题
- 开发流程
- 指定公钥文件