如何在Git中的另一个分支上“覆盖”而不是“合并”一个分支?


257

我有两个分支,email并且stagingstaging是最新的版本,我不再需要email分支中的旧更改,但是我不想删除它们。

所以,我只是想的所有内容转储stagingemail让他们都指向同一个commit。那可能吗?


Answers:


196

您可以使用“我们的”合并策略:

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head

26
我试过了,对我来说似乎倒退了?这不是将电子邮件的内容转储到暂存中吗?
2014年

27
@Max我也有同样的困惑,这给我带来了很多麻烦。您需要从较新的分支(暂存)中执行此命令,然后对旧分支(电子邮件)进行正常的合并/ PR。
MrGlass 2014年

7
为什么;在每个命令的末尾?我没有使用它;,但它似乎正在工作。同样,这个答案是不完整的,第三步是检出旧分支(电子邮件),然后再次与暂存合并。
Rosdi Kasim 2014年

4
git rebase -s theirs <oldbranc> <newbranch> 也可以工作(无论您位于哪个分支)。请注意,在重新设置基准时,“他们的”实际上是新分支,因为“我们的”是我们当前将提交应用到的头。
罗尔夫(Rolf)2015年

4
@Rolf:但是rebase将摆脱合并信息并展平历史记录。不一定是你所追求的。如果您正在使用已发布的历史记录,也不是一个好主意。
knittl

99

如果只希望两个分支“ email”和“ staging”相同,则可以标记“ email”分支,然后将“ email”分支重置为“ staging”一个:

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

您也可以将“ staging”分支重新设置在“ email”分支上。但是结果将包含两个分支的修改。


1
您可能是说git checkout,据git check我所知不存在
knittl 2011年

4
没错,我习惯于使用tab命令完成git命令,所以我总是写“ git check <TAB>”来写“ git checkout”!已更正。
西尔文·德夫雷斯内

16
git reset会中断其他克隆您的存储库的存储库
Geoffrey De Smet 2012年

我相信这是正确的答案。email分支的头应该指向相同的头,staging并且它们都将具有相同的提交,相同的历史记录。
cicerocamargo

76

我已经看到了几个答案,这是唯一使我能够在没有任何冲突的情况下进行修复的过程。

如果要从branch_old中的branch_new中进行所有更改,则:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

一旦应用了这四个命令,您就可以毫无问题地推送branch_old


5
您的答案确实最适合我的问题,因为我不想重置HEAD,只需在将内容合并到较旧的文件时在较新的分支中声明对较新文件的偏好,就可以正常工作!+1
炉子

在“我们的合并”之后,我将branch_new推到了远程,这种方法对我有用。我有必要推动吗?还是没有它会起作用?(不确定是否将使用本地分支或远程分支)。谢谢!
aspergillusOryzae

您为什么不能简单地执行以下操作?git的结帐branch_old混帐合并-s取自他们branch_new线索stackoverflow.com/questions/14275856/...
日普达曼

它说,找不到合并策略“他们的”。
arango_86

非常适合我,其优点是无需重设任何内容
Romain

68

其他答案给了我正确的线索,但它们并没有完全帮助。

这对我有用:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

如果没有与我们的战略合并的第四步,则该推送将被视为非快速更新,并且将被拒绝(GitHub)。


这使合并提交消息出错,但是,很好。
cdunn2001

cdunn2001,我很好奇。您期望的合并提交消息是什么,以及如何将其弄乱了?
Shyam Habarakada 2012年

它说:“将远程跟踪分支的“来源/电子邮件”合并到电子邮件中”。它没有提到分期。不过没什么大不了的。只需修改提交,或使用即可merge -m 'This is not my beautiful house.' -s ours origin/email
cdunn2001

@ShyamHabarakada,正如您所说,我会遇到有关非快速更新的问题。因为当我执行第四步时什么也没有发生。
kommradHomer

第4步要求您使用来源/电子邮件,而不仅仅是本地电子邮件。
特拉维斯·里德2013年

45

如果您像我一样,并且不想处理合并,则可以执行上述步骤,但使用force而不是merge除外,因为这会产生分散注意力的日志记录:

git checkout email
git reset --hard staging
git push origin email --force

注意:仅当您真正不想再在电子邮件中看到这些内容时,才可以。


1
git push原始电子邮件--force对我不起作用,因为Step2左分支分散了。所以在Step2之后,这就是我的工作:git reset origin / email然后git push
user3505394 '16

2
这正是问题所在:“如何覆盖而不是合并”。应该接受答案。
jozols

17

我想合并两个分支,以便使用其中的内容old_branch更新所有内容new_branch

对我来说,这就像一个魅力:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch

10

怎么样:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease

@emptywalls,因为它执行强制推送而没有警告用户服务器可以拒绝它,也没有解释为什么需要它。也就是说,对于一个开发人员项目来说,这是一个可行的选择
David Costa

@DavidCosta为什么这会被服务器拒绝?这是一个简单的删除电子邮件分支并将分段复制到电子邮件” ...所以我只想将“分段”的所有内容转储到“电子邮件”中,以便它们都指向同一提交”-正是这种情况这里。
Arek S

@ArekS如果分支被设置为“ protected”(例如在GitLab中),则可以被服务器端挂钩拒绝。问题是,如果其他人在此操作之前从电子邮件派生了他的分支,然后尝试推送,则引用不再匹配(因为某些提交已消失)
David Costa

1
我将原始文档从--force编辑为--force-with-lease,以一种非破坏性的方式完成了工作。
frandroid

1
如果只想吹掉一个分支并从源分支开始将其清除,这是最好的方法。
Shane

6

其他答案似乎不完整。
我已经在下面进行了充分的尝试,并且工作正常。

注意:
1.为安全起见,在尝试以下操作之前,请复制存储库的副本。

详细信息:
1.所有开发都在dev分支中进行
。2. qa分支与dev的副本相同
。3.不时需要将dev代码移入/覆盖到qa分支。

所以我们需要覆盖dev分支中的qa分支

第1部分:
使用以下命令,旧的qa已更新为较新的dev:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

最后推送的自动评论如下:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

此注释看起来是相反的,因为上面的序列也看起来是相反的

第2部分:

下面是开发人员中意外的,新的本地提交,不必要的提交,
因此,我们需要丢弃并保持开发不变。

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

第3部分:
验证一切均符合预期:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

就这样。
1.现在旧的qa已被新的dev分支代码覆盖
。2. local是干净的(远程原点/ dev未被修改)


6

最简单的方法是:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

现在,电子邮件分支和分段是相同的。


2
警告:这会删除email分支上的所有提交。这就像删除email分支并在分支的开头重新创建它一样staging
卡梅隆·哈德森

2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging

1
如果将注释与命令中的合并注释分开,则此答案对我来说会更清楚。简要说明-X的作用及其对合并的影响。不过谢谢 让我抬起头来:)
noelicus '19

@noelicus感谢您的评论,您是对的。我将来可能会编辑答案。
威拉

0

该分支不会更改原始的较新分支,并为您提供了在最终提交之前进行进一步修改的机会。

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.