git fetch 完成了仅有的但是很重要的两步:
- 从远程仓库下载本地仓库中缺失的提交记录
- 更新远程分支指针(假设为 o/master)
git fetch
实际上将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态:
git fetch
通常通过互联网(使用 http:// 或 git:// 协议) 与远程仓库通信。
git fetch 不会做的事
git fetch
并不会改变你本地仓库的状态。它不会更新你的 master 分支,也不会修改你磁盘上的文件。
理解这一点很重要,因为许多开发人员误以为执行了 git fetch 以后,他们本地仓库就与远程仓库同步了。它可能已经将进行这一操作所需的所有数据都下载了下来,但是并没有修改你本地的文件。
所以,你可以将 git fetch
的理解为单纯的下载操作。
合并远程分支
当远程分支中有新的提交时,你可以像合并本地分支那样来合并远程分支。也就是说就是你可以执行以下命令:
git cherry-pick o/master
git rebase o/master
git merge o/master
- 等等
实际上,由于先抓取更新再合并到本地分支这个流程很常用,因此 Git 提供了一个专门的命令来完成这两个操作,它就是 git pull
。
git pull
git pull
就是 git fetch
+ git merge o/master
。
当你想要 push 你的新提交时,发现远程仓库在你上次拉取以后已经又有了改变,也就是说你的新 commit 是基于旧提交的修改,这种情况下 Git 是不允许你进行 push 操作的,你需要使自己的工作基于远程的提交,这个过程可以用以下命令:
git fetch; git merge o/master
git fetch; git rebase o/master
- 最简单的当然还是
git pull -r
(git pull --rebase
的缩写)
然后再 git push
就没问题了。
在开发社区里,有许多关于 merge 与 rebase 的讨论。以下是关于 rebase 的优缺点:
- 优点:rebase 使你的提交树变得很干净, 所有的提交都在一条线上
- 缺点:rebase 修改了提交树的历史。比如,提交 C1 可以被 rebase 到 C3 之后。这看起来 C1 中的工作是在 C3 之后进行的,但实际上是在 C3 之前。
一些开发人员喜欢保留提交历史,因此更偏爱 merge。而其他人可能更喜欢干净的提交树,于是偏爱 rebase。仁者见仁,智者见智。
git push
git push
负责将你的变更上传到指定的远程仓库。远程仓库中的 master 分支被更新,我们的远程分支(o/master)也同样会被更新。
未指定参数时,Git 是通过当前检出分支的属性来确定远程仓库以及要 push 的目的地的。我们可以为 push 指定参数,语法是 git push <remote> <place>
。这句话的含义是:切到本地仓库中的 <place> 分支,获取所有的提交,再到远程仓库 <remote> 中找到 <place> 分支,将远程仓库中没有的提交记录都添加上去,搞定之后告诉我。
如果不指定参数,且 HEAD 没有跟踪任何分支,git push
不会有任何响应:
要同时为源和目的地指定 <place> 的话,只需要用冒号将二者连起来就可以了 git push origin <src>:<dst>
。
注意如果 <src> 传了个空值过去,会删除该远程分支。
从远程库删除某些文件但保留本地的文件
有时我们会误把一些不必要的文件(如目标文件、log 日志等)提交并推送到了远程库,现在希望从远程库删除这些文件但保留本地的文件,可以像这样 执行:
git rm -r --cached dir1
git rm --cached dir2/*.pyc
git commit -m "remove irrelated files"
git push origin branch1