git命令使一个分支像另一个分支

我正在试图改变一个分支,并把它带回与它分离的上游相同。 这些变化都是本地化的,并且已经被推到了github上,所以git reset或者git rebase都不是真正可行的,因为它们改变了历史,这对于已经被推动的分支来说是一件坏事。

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

我可以在上游创build一个新的分支,但是我真的很喜欢一个合并,就修订历史而言,应用所有的修改来使我的分支再次与上游一致,这样我就可以安全地推动这个改变没有破坏历史。 有这样一个命令或一系列命令吗?

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

 mv -f $3 $2 exit 0 

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 

这有利于将上游祖先logging为第一父母,以便合并意味着“吸收这个过时的主题分支”而不是“摧毁这个主题分支并用上游代替”

(编辑2011):

OP在这个博客文章中报告了这个工作stream程:

为什么我又要这个?

只要我的回购与公共版本无关,这一切都很好,但是现在我想要和其他团队成员和外部贡献者一起在WIP上进行合作的能力,我想确保我的公共分支机构因为它现在在GitHub和公共版上,所以别人可以分支并从中撤出,也就是说,不会再发生重置,并重置已经推送到远程备份的东西。

所以,我留下了我应该如何进行。
99%的时间我的副本将进入上游主,所以我想工作我的主人,大部分时间推入上游。
但是每过一段时间,我所拥有的东西都会因上游的东西而失效,我会放弃我的一部分。
在这一点上,我想让我的主人与上游同步,但是不能破坏我公开推动的主人的任何提交点。 也就是说,我想要一个上游合并结束与变更,使我的副本相同的上游
这就是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 

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 

有时你会想要这样做,而不是因为你的历史中有“垃圾”,但也许是因为你想在公共仓库中改变开发的基线,在这里避免重新分配


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 

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 

git merge --strategy=theirs模拟#6

(由同一个Michael Gebetsroither提出):

迈克尔Gebetsroither插话,声称我是“作弊”),并提供了另一个解决scheme与低级pipe道命令:

(它不会是混帐,如果它不可能使用git only命令,所有在git diff / patch / apply中都不是真正的解决scheme;)。

 # get the contents of another branch git read-tree -u --reset <ID> # selectivly merge subdirectories # eg 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 

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

 $ git fetch origin $ git merge origin/master -s recursive -Xtheirs 

这使您的本地回购与原点同步,并保留历史。

这听起来像你只需要做:

 $ git reset --hard origin/master 

如果没有改变推上游,你只是希望上游分支是你当前的分支,这将做到这一点。 这样做在本地没有害处, 但是你将失去任何未被推到掌握的地方变化**。

**实际上,如果您在本地犯了这些错误,那么这些修改仍然存在,因为这些修改仍然在您的git reflog ,通常至less需要30天。

另一个模拟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 

双重重置的替代scheme是应用反向补丁:

 git diff --binary ref-to-be-merged | git apply -R --index 

还有一种方法,没有pipe道命令的帮助 – 恕我直言最直接的。 假设你想效仿2个分支机构的“他们的”情况:

 head1=$(git show --pretty=format:"%H" -s foo) head2=$(git show --pretty=format:"%H" -s bar) tree=$(git show --pretty=format:"%T" -s bar) newhead=$(git commit-tree $tree -p $head1 -p $head2 <<<"merge commit message") git reset --hard $newhead 

这合并任意数量的头(上面的例子中的2),使用其中之一的树(上例中的bar,提供他们的树),忽略任何diff / file问题(commit-tree是低级命令,所以它不关心那些)。 请注意,头可以只是1(所以相当于“他们的”樱桃采摘)。

请注意,哪个父头被首先指定,可以影响一些东西(请参阅,例如 – git-log命令的first-parent) – 请记住这一点。

可以使用任何其他能够输出树和提交哈希的东西 – 无论用于parsing(cat-file,rev-list,…)。 你可以使用git commit来追踪所有内容 – 以交互方式美化提交消息。

切换到远程上游分支,并执行合并策略设置为oursgit merge

 git checkout origin/master git merge dev --strategy=ours git commit ... git push 

所有的历史将仍然存在,但你会有一个额外的合并提交。 这里的重要事情是从你想要的版本开始,并将其与分支github实际上在ours的合并。

手足无措,但是地狱,有什么可能出错?

  • 看看你想看起来像Y的分支X.
  • cp -r .git / tmp
  • 检查分支Y.
  • rm -rf .git && cp -r /tmp/.git。
  • 提交和推动任何区别
  • DONE。