珍藏多年的 Git 问题和操作清单( 二 )


3. git pull
拉取远程主机某分支的更新,再与本地的指定分支合并(相当与fetch加上了合并分支功能的操作)
4. git push
将本地分支的更新,推送到远程主机,其命令格式与 git pull 相似
5. 分支操作

  • 使用 Git 下载指定分支命令为: git clone -b 分支名仓库地址
  • 拉取远程新分支 git checkout -b serverfix origin/serverfix
  • 合并本地分支 git merge hotfix :(将 hotfix 分支合并到当前分支)
  • 合并远程分支 git merge origin/serverfix
  • 删除本地分支 git branch -d hotfix :(删除本地 hotfix 分支)
  • 删除远程分支 git push origin --delete serverfix
  • 上传新命名的本地分支: git push origin newName ;
  • 创建新分支: git branch branchName :(创建名为 branchName 的本地分支)
  • 切换到新分支: git checkout branchName :(切换到 branchName 分支)
  • 创建并切换分支: git checkout -b branchName :(相当于以上两条命令的合并)
  • 查看本地分支: git branch
  • 查看远程仓库所有分支: git branch -a
  • 本地分支重命名: git branch -m oldName newName
  • 重命名远程分支对应的本地分支: git branch -m oldName newName
  • 把修改后的本地分支与远程分支关联: git branch --set-upstream-to origin/newName
五、优化操作
1. 拉取代码 pull --rebase
在团队协作过程中,假设你和你的同伴在本地中分别有各自的新提交,而你的同伴先于你 push 了代码到远程分支上,所以你必须先执行 git pull 来获取同伴的提交,然后才能 push 自己的提交到远程分支 。
而按照 Git 的默认策略,如果远程分支和本地分支之间的提交线图有分叉的话(即不是 fast-forwarded),Git 会执行一次 merge 操作,因此产生一次没意义的提交记录,从而造成了像上图那样的混乱 。
【珍藏多年的 Git 问题和操作清单】其实在 pull 操作的时候,,使用 git pull --rebase 选项即可很好地解决上述问题 。加上 --rebase 参数的作用是,提交线图有分叉的话,Git 会 rebase 策略来代替默认的 merge 策略 。
假设提交线图在执行 pull 前是这样的:
A---B---C remotes/origin/master / D---E---F---G master如果是执行 git pull 后,提交线图会变成这样:
A---B---C remotes/origin/master /D---E---F---G---H master结果多出了 H 这个没必要的提交记录 。如果是执行 git pull --rebase 的话,提交线图就会变成这样:
remotes/origin/master | D---E---A---B---C---F'---G' masterF G 两个提交通过 rebase 方式重新拼接在 C 之后,多余的分叉去掉了,目的达到 。
小结
大多数时候,使用 git pull --rebase 是为了使提交线图更好看,从而方便 code review 。
不过,如果你对使用 git 还不是十分熟练的话,我的建议是 git pull --rebase 多练习几次之后再使用,因为 rebase 在 git 中,算得上是『危险行为』  。
另外,还需注意的是,使用 git pull --rebase 比直接 pull 容易导致冲突的产生,如果预期冲突比较多的话,建议还是直接 pull 。
注意:
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
2. 合代码 merge --no-ff
上述的 git pull --rebase 策略目的是修整提交线图,使其形成一条直线,而即将要用到的 git merge --no-ff <branch-name> 策略偏偏是反行其道,刻意地弄出提交线图分叉出来 。
假设你在本地准备合并两个分支,而刚好这两个分支是 fast-forwarded 的,那么直接合并后你得到一个直线的提交线图,当然这样没什么坏处,但如果你想更清晰地告诉你同伴: 这一系列的提交都是为了实现同一个目的 ,那么你可以刻意地将这次提交内容弄成一次提交线图分叉 。
执行 git merge --no-ff <branch-name> 的结果大概会是这样的:
珍藏多年的 Git 问题和操作清单

文章插图
 
git merge --no-ff
中间的分叉线路图很清晰的显示这些提交都是为了实现 complete adjusting user domains and tags
更进一步
往往我的习惯是,在合并分支之前(假设要在本地将 feature 分支合并到 dev 分支),会先检查 feature 分支是否『部分落后』于 远程 dev 分支 :
git checkout devgit pull # 更新 dev 分支git log feature..dev如果没有输出任何提交信息的话,即表示 feature 对于 dev 分支是 up-to-date 的 。如果有输出的话而马上执行了 git merge --no-ff 的话,提交线图会变成这样:
珍藏多年的 Git 问题和操作清单


推荐阅读