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

标签 git github branching-and-merging

我正在尝试获取一个有更改的分支并将其恢复为与它从中分离出来的上游相同。这些更改都是本地的,并且已经推送到 github,所以 git resetgit rebase 都不是真正可行的,因为它们改变了历史,这对分支来说是一件坏事已经推送了。

我也尝试过使用各种策略进行 git merge,但没有一个可以撤消本地更改,即如果我添加了一个文件, merge 可能会使其他文件恢复原状,但我仍然会有上游没有的那个文件。

我可以在上游创建一个新分支,但我真的很喜欢 merge ,在修订历史方面应用所有更改来获取我的分支并使其再次与上游相同,这样我就可以安全地在不破坏历史的情况下 push 这种变化。是否有这样的命令或系列命令?

最佳答案

您可以使用自定义 merge 驱动程序“keepTheirs”将您的上游分支 merge 到您的dev分支:
参见“git merge -s theirs” needed — but I know it doesn't exist”。
在您的情况下,只需要一个 .gitattributes 和一个 keepTheirs 脚本,例如:

mv -f $3 $2
exit 0

git merge --strategy=theirs 模拟#1

显示为 merge ,上游作为第一个父级。

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

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

This has the benefit of recording the upstream ancestor as the first parent, so that the merge means "absorb this out-of-date topic branch" rather than "destroy this topic branch and replace it with upstream".

(2011 年编辑):

此工作流程已在 blog post by the OP 中报告:

Why do I want this again?

As long as my repo had nothing to do with the public version, this was all fine, but since now I'd want the ability to collorate on WIP with other team members and outside contributors, I want to make sure that my public branches are reliable for others to branch off and pull from, i.e. no more rebase and reset on things I've pushed to the remote backup, since it's now on GitHub and public.

So that leaves me with how I should proceed.
99% of the time my copy will go into the upstream master, so I want to work my master and push into upstream most of the time.
But every once in a while, what I have in wip will get invalidated by what goes into upstream and I will abandon some part of my wip.
At that point I want to bring my master back in sync with upstream, but not destroy any commit points on my publicly pushed master. I.e. i want a merge with upstream that ends up with the changeset that make my copy identical to upstream.
And that's what git merge --strategy=theirs should do.


git merge --strategy=theirs 模拟 #2

显示为 merge ,我们的作为第一个父级。

(由 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

blog post mentions :

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

sometimes you do want to do this, and not because you have "crap" in your history, but perhaps because you want to change the baseline for development in a public repository where rebasing should be avoided.


git merge --strategy=theirs 模拟 #4

(同一篇博文)

Alternatively, if you want to keep the local upstream branches fast-forwardable, a potential compromise is to work with the understanding that for sid/unstable, the upstream branch can from time to time be reset/rebased (based on events that are ultimately out of your control on the upstream project's side).
This isn't a big deal and working with that assumption means that it's easy to keep the local upstream branch in a state where it only takes fast-forward updates.

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 提出):

Michael Gebetsroither chimed in, claiming I was "cheating" ;) and gave another solution with lower-level plumbing commands:

(it wouldn't be git if it wouldn't be possible with git only commands, everything in git with diff/patch/apply isn't a real solution ;).

# 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

git merge --strategy=theirs 模拟 #7

The necessary steps can be described as:

  1. Replace your worktree with upstream
  2. Apply the changes to the index
  3. Add upstream as the second parent
  4. Commit

The command git read-tree overwrites the index with a different tree, accomplishing the second step, and has flags to update the work tree, accomplishing the first step. When committing, git uses the SHA1 in .git/MERGE_HEAD as the second parent, so we can populate this to create a merge commit. Therefore, this can be accomplished with:

git read-tree -u --reset upstream                 # update files and stage changes
git rev-parse upstream > .git/MERGE_HEAD          # setup merge commit
git commit -m "Merge branch 'upstream' into mine" # commit

关于使一个分支像另一个分支的 git 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4911794/

相关文章:

git - 为什么我要将 "remote-tracking branch ' origin/develop' merge 到 develop”?

git - 应用 stash 提交 '...' 失败,原因是“正在应用...eclipse 中的 egit 错误

Git:如何找到提交之间的最短路径

Git 错误 : ! [rejected] master -> master (non-fast-forward)

git - 如何将项目的 Git 存储库上传到 GitHub?

git - 如何在团队成员之间共享大型 git merge

git - 如何添加 git 子模块并将其标记到版本中?

android - 在 Git 中创建分支以向 Android 应用程序添加新功能

javascript - 实时预览与代码扩展

version-control - Perforce 中的 Git 樱桃选择等价物?