我们有一个项目,我们不得不一次回顾一下Git的历史,并从旧的提交开始创建一个新的分支(在这里称为“ new_branch”)。现在,所有开发都在new_branch中进行,并且在分支创建之后,旧的Master不再有用。因此,我们现在遇到的情况如下:
C1 = Commit 1, C2 = Commit 2, etc.
C1
|
C2
|\
C3 \
| \
... \
| \
Master --> C17 \
\
C18
|
...
|
C37 <-- new_branch
所以我现在想做的是放弃(撤消?)分支点之后,即C3到C17,在Master中所做的所有提交。至少,这就是我想做的?我的意思是,C3至C17现在已无用,如果我可以撤消它们,则可以将new_branch合并回Master,以使Master再次有用。
所以我的问题是,这是实现我再次使用Master的目标的正确方法吗?以及应该使用哪个命令(在Linux的命令行中使用Git)撤消C3到C17的提交?这是一个工作项目,因此正确无误非常重要。
答案 0 :(得分:4)
最直接的解决方案是简单地将new_branch
推到原点的master
上:
git checkout new_branch
git push -f master
然后使用以下几种方法之一修复本地master
:
git reset --hard origin/master
(在分支master
上)git branch -D master
(不在分支master
上,再次拉动以获取更新的分支)在这种情况下,无需使用master
对现有的new_branch
进行基础调整。
(显然)这将消除现有的master
并将其替换为new_branch
的内容和历史记录。 确定您的意图。
正如Romain指出的那样,使用git branch -f
消除了本地修复步骤:
git branch -f master new_branch && git push -f origin master
因为它也将分支指针移动到本地。
与许多git问题一样,有很多方法可以解决此问题,其他答案可能同样可行。
答案 1 :(得分:2)
执行此操作有两种通用方法;每个都有缺点,所以这取决于您所处的情况。每种方法也都有差异,但权衡较小...
第一种方法是重写master
的历史记录。这只是意味着移动master
的方式会从其历史记录中删除当前属于其历史记录的某些提交。
任何历史重写,无论您如何操作都具有一定的成本-因此,通常最好以最简单的方式来满足您的要求。在这种情况下,可能是
git checkout master
git reset --hard new_branch
git push --force-with-lease
这实际上与msanford建议的方法相似,但是有两个优点。首先,它更加简洁(因为它首先更新了本地分支并将其用作更新rmeote的设置)。其次,将-f
替换为--force-with-lease
可以提供一些额外的安全性,因为它可以确保您没有意识到遥控器没有任何新承诺。 (在您的特定情况下,这可能不是什么大问题;但这是一个很好的习惯。)
对分支的历史记录进行重写的成本已在存储库之间共享(即push
ed,然后-至少有可能-fetch
ed或pull
写入其他存储库)是共享分支的其他存储库将看到分支以“意外”的方式移动,并且必须进行恢复。恢复过程记录在git rebase
文档的“从上游资源恢复中”部分中。在进行此操作时,与整个团队进行协调非常重要,就好像任何团队成员在恢复时做错了什么一样,它都可以撤消历史记录的重写。
好处是,您的历史记录非常好,根本不会显示已删除的提交。 (但是要注意,如果这些提交已被共享,则您无能为力,无法确保它们“永远消失”。如果它们包含敏感信息,那将是一个更大的问题,并且该信息基本上必须被视为已泄露-尽管存在您可以采取的步骤至少可以阻止此类信息的进一步传播。)
因此,如果您可以与回购的所有用户进行实际协调,这是一个不错的选择。但是,如果不能,那还有另一种方法。
第二种方法是撤消对主服务器的更改-即将其还原回C2
-然后合并new_branch
。这符合通常“分支到”分支的方式,因此不承担重写的费用。但是,这意味着被遗弃的提交(及其撤消)在历史上将永远存在。
git checkout master
git revert -n C3..HEAD
git commit
git merge new_branch
这为您提供了类似的历史记录
C1 - C2 - C3 - ... - C17 - R -- M <--(master)
\ /
C18 - ........... - C37 <--(new_branch)
R
使master
的外观与C2
一样,而M
是对此的较新更改的简单合并。
如果您从-n
命令中省略了revert
选项,则可以跳过commit
命令,但是您将获得一个单独的提交来撤消{{1} }至C3
。如果您真的强烈认为这样做会更好,但也有一些技巧可以将更改的撤销嵌入到合并提交本身中,但是它会创建“恶意合并”,即隐藏更改并可能混淆用户和某些将来操作的合并像C17
。
缺点是历史比较混乱。 (如果您确实需要历史记录来记录自己的位置,那么可以说它更准确;但是它肯定更复杂,并且可以显示您可能不再需要的信息。如果还原的提交包含敏感信息,则肯定不适合你不想继续传播。)
但是,如上所述,它遵循正常的分支移动模式,因此避免了重写历史记录的费用。
同样,这取决于您所处的情况。
答案 2 :(得分:0)
因此,如果要擦除c3-c17,则可以签出c3,然后使用merge将新分支的更改放在最上面。然后,如果您将其推回主机,则c3-c17将消失