做网站一定需要自己买主机吗,网站建设7大概要多久,张家港手机网站建设,云主机多个网站1. 挑选提交合并 git cherry-pick
对于多分支的代码库#xff0c;将代码从一个分支转移到另一个分支是一种常见的需求#xff0c;这可以分成两种情况#xff1a;一种情况是#xff0c;你需要另一个分支的所有代码变动#xff0c;那么就采用 git merge#xff1b;另一种情…1. 挑选提交合并 git cherry-pick
对于多分支的代码库将代码从一个分支转移到另一个分支是一种常见的需求这可以分成两种情况一种情况是你需要另一个分支的所有代码变动那么就采用 git merge另一种情况是你只需要部分代码变动某几个提交这时可以采用 git cherry-pick语法为git cherry-pick commitHash将指定提交合并到另一个分支。 举例来说假设代码仓库有 master 和 feature 两个分支提交历史如下现在将 feture 分支的提交 f 应用到 master 分支。
a - b - c - d Master \ e - f - g Feature
# 切换到 master 分支
$ git checkout master# Cherry pick 操作
$ git cherry-pick f
上面的操作完成以后代码库就变成了下面的样子master 分支的末尾增加了一个提交 f。
a - b - c - d - f Master \ e - f - g Feature
# 参数为分支名表示转移该分支的最新一次提交。
$ git cherry-pick feature# 一次转移多个提交
$ git cherry-pick HashA HashB
# 上述命令能将 A 和 B 两个提交应用到当前分支这会在当前分支生成两个对应的新提交。# 转移一系列的连续提交可以使用下面的简便语法
$ git cherry-pick A..B
# 上述命令将转移从 A 到 B 不包括A的所有提交A、B的顺序一定要正确提交 A 必须早于提交 B否则命令将失败但不会报错。# 转移从 A 到 B 包括A的所有提交
$ git cherry-pick A^..B 2. 变基 git rebase
在 Git 中整合来自不同分支的修改除了 merge还有一种方法变基 rebase。git rebase 命令基本是一个自动化的 cherry-pick 命令它计算出一系列的提交然后在其地方以同样的顺序一个一个的 cherry-pick 它们。
Git 中有一些修改会覆盖提交历史列举如下在使用这些命令时需要谨慎操作以免不小心覆盖提交历史导致代码丢失或者出现其他问题。 使用 git commit --amend 命令修改最近一次提交的信息会覆盖最近一次提交的记录。使用 git rebase 命令修改提交记录这会修改提交的 SHA-1 校验和覆盖提交历史。使用 git reset 命令回滚到之前的提交这会删除之后的提交历史。使用 git push --force 命令强制推送修改这会覆盖远程分支的提交历史。 2.1 Case 1git rebase upstream
假设在一个项目开发过程中分叉到两个不同分支每个分支都提交了更新。 可以使用 merge 命令整合分支它会把两个分支的最新快照C3 和 C4以及二者最近的共同祖先C2进行三方合并合并的结果是生成一个新的快照并提交。 还有一种方法使用变基 git rebase 整合分支git rebase 的语法可以简写为git rebase [--onto newbase] [upstream [branch]]表示将 branch 分支从 upstream 开始的提交应用到 newbase 分支上。具体来说它会将 branch 分支自 upstream 之后的提交移动到 newbase 分支的最新提交之后使得 branch 分支的提交历史看起来像是在 newbase分支的基础上进行的。
可以省略的参数是 newbase 和 branch如果省略 --onto 参数将以 upstream 参数指定的分支作为基底进行变基操作。也就是说将当前所在分支HEAD 指向的分支与 upstream 参数指定的分支之间的差异应用到 upstream分支上如果省略 branch将把当前所在分支即 HEAD 指向的分支作为 branch 参数传递给 git rebase 命令。 $ git checkout experiment$ git rebase master 接下来运行 git checkout master 回到 master 分支然后运行 git merge experiment 进行一次快进合并。C4 指向的快照就和使用 merge 得到的 C5 指向的快照一模一样这两种整合方法的最终 结果没有任何区别但是变基使得提交历史更加整洁。 你在查看一个经过变基的分支的历史记录时会发现尽管实际的开发工作是并行的但它们看上去就像是串行的一样提交历史是一条直线没有分叉。
一般这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁例如向某个其他人维护的项目贡献代码时。在这种情况下你首先在自己的分支里进行开发当开发完成时你需要先将你的代码变基到 origin/master 上然后再向主项目提交修改。这样的话该项目的维护者就不再需要进行整合工作只需要快进合并便可。
2.2 Case2git rebase [--onto newbase] [upstream [branch]]
假设你的项目提交历史如下你创建了一个特性分支 server为服务端添加了一些功能提交了 C3 和 C4。然后从 C3 上创建了特性分支 client为客户端添加 了一些功能提交了 C8 和 C9。 最后你回到 server 分支又提交了 C10。 你希望将 client 中的修改合并到 master 主分支并发布但暂时并不想合并 server 中的修改因为它们还需要经过更全面的测试。这时你可以使用 git rebase 命令的 --onto 选项选择在 client 分支里但不在 server 分支里的修改即 C8 和 C9将它们应用在 master 分支上。
运行命令git rebase --onto master server client其含义是“取出 client 分支找出处于 client 分支和 server 分支的共同祖先之后的修改然后把它们在 master 分支上重放一遍”。然后将 client 合并到 master。
$ git rebase --onto master server client
$ git checkout master
$ git merge client
$ git rebase master server
$ git checkout master
$ git merge server$ git branch -d client
$ git branch -d server 2.3 Case3变基使用不当的风险 警告不要对仓库外有副本的分支执行变基。如果你遵循这条金科玉律就不会出差错。 否则人民群众会仇恨你你的朋友和家人也会嘲笑你唾弃你。-- Scott Chacon 只要你把变基命令当作是在推送前清理提交使之整洁的工具并且只在从未推送至共用仓库的提交上执行变基命令就不会有事。 假如在那些已经被推送至公用仓库的提交上执行变基命令并因此丢弃了一些别人的开发所基于的提交那你就有大麻烦了你的同事也会因此鄙视你。
2.3.1 变基使用不当的例子
假设你从一个中央服务器克隆然后在它的基础上进行了一些开发提交历史如图所示 一段时间后其他项目成员向中央服务器提交了一些修改其中包括一次合并。 你抓取了这些在远程分支上的修改并将其合并到你本地的开发分支你的提交历史如下 接下来这个成员又决定把合并操作回滚改用变基并用 git push --force 命令强制推送修改这会覆盖远程分支的提交历史。 此时你从服务器抓取更新会发现多出来一些新的提交。如果你执行 git pull 命令你将合并来自两条提交历史的内容生成一个新的合并提交 C8。 此时如果你执行 git log 命令你会发现有两个提交的作者、日期、日志居然是一样的这会令人感到混乱。 此外如果你将这一堆又推送到服务器上实际上是将那些已经被变基抛弃的提交又找了回来这会令人感到更加混乱。很明显对方并不想在提交历史中看到 C4 和 C6因为之前就是他把这两个提交通过变基丢弃的。
2.3.2 解决方法 如果团队中的某人强制推送并覆盖了一些你所基于的提交你需要做的就是检查你做了哪些修改以及他们覆盖了哪些修改。 方案1git fetch git rebase在一个被变基然后强制推送的分支上再次执行变基
对于这种有人推送了经过变基的提交并丢弃了你的本地开发所基于的一些提交不要使用 git pull而是先 git fetch再执行 git rebase teamone/master, Git 将会 检查哪些提交是我们的分支上独有的C2C3C4C6C7检查其中哪些提交不是合并操作的结果C2C3C4检查哪些提交在对方覆盖更新时并没有被纳入目标分支C2 和 C3C4 其实就是 C4把查到的这些提交应用在 teamone/master 上面 想要上述方案有效还需要对方在变基时确保 C4 和 C4 是几乎一样的。 否则变基操作将无法识别并新建另一个类似 C4 的补丁而这个补丁很可能无法整洁的整合入历史因为补丁中的修改已经存在于某个地方了。
方案2使用 git pull --rebase 而不是直接用 git pull
如果你或你的同事在某些情形下不得不强制推送经过变基的提交请一定要通知每个人执行 git pull --rebase 命令这样尽管不能避免麻烦但能有所缓解。