用于使一个分支像另一个分支的git命令

Arn*_*sen 70 git github branching-and-merging

我试图采取一个变化的分支,并将其恢复为与它分离的上游相同.这些变化都是本地的,并且已被推送到github,因此它们都没有git reset或者git rebase真的可行,因为它们改变了历史,这对于已经被推动的分支来说是一件坏事.

我也尝试git merge了各种策略,但没有一个撤消本地更改,即如果我添加了一个文件,合并可能会使其他文件重新排队,但我仍然会有上游没有的文件有.

我可以在上游创建一个新的分支,但我真的很喜欢合并,在修订历史方面应用所有更改来获取我的分支并使其与上游相同,以便我可以安全地推动该更改没有破坏历史.是否有这样的命令或一系列命令?

Von*_*onC 94

您可以将上游分支合并到您的dev分支,使用自定义合并驱动程序"keepTheirs":
请参阅" " git merge -s theirs"需要 - 但我知道它不存在 ".
在您的情况下,只.gitattributes需要一个,并且keepTheirs脚本如下:

mv -f $3 $2
exit 0
Run Code Online (Sandbox Code Playgroud)

git merge --strategy=theirs 模拟#1

显示为合并,上游为第一个父级.

Jefromi提到(在评论中)merge -s ours,通过将您的工作合并到上游(或从上游开始的临时分支),然后将您的分支快速转发到该合并的结果:

git checkout -b tmp origin/upstream
git merge -s ours downstream         # ignoring all changes from downstream
git checkout downstream
git merge tmp                        # fast-forward to tmp HEAD
git branch -D tmp                    # deleting tmp
Run Code Online (Sandbox Code Playgroud)

这有利于将上游祖先记录为第一个父级,因此合并意味着"吸收这个过时的主题分支"而不是"销毁此主题分支并将其替换为上游".

(编辑2011):

OP的这篇博客文章报道了这个工作流程:

为什么我又想要这个?

只要我的回购与公共版本无关,这一切都很好,但是从现在开始我想要与其他团队成员和外部贡献者一起使用WIP,我想确保我的公共分支机构是可靠的其他人分支和拉出,即不再对我推送到远程备份的东西进行rebase和重置,因为它现在在GitHub和public上.

所以这让我知道如何继续.
99%的时间我的副本将进入上游主服务器,所以我想工作我的主人并在大多数时间推进上游.
但每隔一段时间,我所拥有的内容wip将因上游的内容而失效,我将放弃我的某些部分wip.
那时我想让我的主人与上游同步,但不会破坏我公开推动的主人的任何提交点.即我想要与上游合并,最终使用变更集,使我的副本与上游相同.
那就是git merge --strategy=theirs应该做的.


git merge --strategy=theirs 模拟#2

显示为合并,我们作为第一个父母.

(由jcwenger提出)

git checkout -b tmp upstream
git merge -s ours thebranch         # ignoring all changes from downstream
git checkout downstream
git merge --squash tmp               # apply changes from tmp but not as merge.
git rev-parse upstream > .git/MERGE_HEAD #record upstream 2nd merge head
git commit -m "rebaselined thebranch from upstream" # make the commit.
git branch -D tmp                    # deleting tmp
Run Code Online (Sandbox Code Playgroud)

git merge --strategy=theirs 模拟#3

这篇博文提到:

git merge -s ours ref-to-be-merged
git diff --binary ref-to-be-merged | git apply -R --index
git commit -F .git/COMMIT_EDITMSG --amend
Run Code Online (Sandbox Code Playgroud)

有时你确实想要这样做,而不是因为你的历史记录中有"废话",但可能是因为你想在公共存储库中更改开发基线,以避免重新定位.


git merge --strategy=theirs 模拟#4

(同一篇博文)

或者,如果您希望保持本地上游分支可快速转发,则可能的妥协是理解对于sid/unstable,上游分支可以不时地重置/重新定位(基于最终输出的事件)您在上游项目方面的控制权).
这不是什么大问题,并且使用该假设意味着很容易将本地上游分支保持在仅进行快速更新的状态.

git branch -m upstream-unstable upstream-unstable-save
git branch upstream-unstable upstream-remote/master
git merge -s ours upstream-unstable
git diff --binary ref-to-be-merged | git apply -R --index --exclude="debian/*"
git commit -F .git/COMMIT_EDITMSG --amend
Run Code Online (Sandbox Code Playgroud)

git merge --strategy=theirs 模拟#5

(由Barak A. Pearlmutter提议):

git checkout MINE
git merge --no-commit -s ours HERS
git rm -rf .
git checkout HERS -- .
git checkout MINE -- debian # or whatever, as appropriate
git gui # edit commit message & click commit button
Run Code Online (Sandbox Code Playgroud)

git merge --strategy=theirs 模拟#6

(由同一个Michael Gebetsroither提出):

Michael Gebetsroither插话,声称我在"作弊";)并给出了另一个低级管道命令的解决方案:

(如果使用git only命令不可能,那就不是git,git中的所有内容都与diff/patch/apply不是真正的解决方案;).

# get the contents of another branch
git read-tree -u --reset <ID>
# selectivly merge subdirectories
# e.g superseed upstream source with that from another branch
git merge -s ours --no-commit other_upstream
git read-tree --reset -u other_upstream     # or use --prefix=foo/
git checkout HEAD -- debian/
git checkout HEAD -- .gitignore
git commit -m 'superseed upstream source' -a
Run Code Online (Sandbox Code Playgroud)

  • 您可以随时使用我们的而不是他们的:检查另一个分支,将您的合并到其中,然后将您的快速转发到合并.`git checkout upstream; git merge -s下游; git checkout下游; git合并上游`.(如果需要,在上游使用临时分支.)这有利于将上游祖先记录为第一个父级,因此合并意味着"吸收这个过时的主题分支"而不是"销毁此主题分支并替换它与上游". (7认同)
  • 哇,谁能想到 --strategy=theirs 可以以多种方式实现。现在如果它可以在下一个版本的 git 中 (2认同)

wup*_*tah 13

听起来像你只需要这样做:

$ git reset --hard origin/master
Run Code Online (Sandbox Code Playgroud)

如果上游没有变化,你只想让上游分支成为你当前的分支,那么这样就可以了.在本地执行此操作无害,您将失去任何未被推送到主人的本地更改**.

**实际上,如果您已在本地提交更改,那么更改仍然存在,因为提交仍将在您的通知中git reflog,通常至少30天.


小智 13

你现在可以很容易地做到这一点:

$ git fetch origin
$ git merge origin/master -s recursive -Xtheirs
Run Code Online (Sandbox Code Playgroud)

这会使您的本地仓库与原点同步,并保留历史记录.

  • `git merge -s recursive -Xtheirs`不会自动合并二进制文件,因此您最终会遇到必须手动解决的冲突情况.基于`git merge -s our`的工作流程不会受此影响. (5认同)

mic*_*has 5

另一个模拟git merge -s theirs ref-to-be-merged:

git merge --no-ff -s ours ref-to-be-merged         # enforce a merge commit; content is still wrong
git reset --hard HEAD^2; git reset --soft HEAD@{1} # fix the content
git commit --amend
Run Code Online (Sandbox Code Playgroud)

双重复位的替代方法是应用反向补丁:

git diff --binary ref-to-be-merged | git apply -R --index
Run Code Online (Sandbox Code Playgroud)

  • @michas在Windows上,^字符用于转义,因此为了将其用作文字,您必须将其本身转义。`git reset --hard HEAD^^2; git reset --soft HEAD@{1}` (2认同)