简体   繁体   English

Git 使用 rebase 重写历史记录

[英]Git rewriting history with rebase

I am currently working on a branch that looks like this我目前正在一个看起来像这样的分支上工作

--A------B (master)
        / \
----C--D   E--F (feature_branch, HEAD)

I've been trying my best to fix it without success :( git-rebase <A_SHA1> doesn't seem to work at all. There are currently only two branches: master and feature_branch .我一直在尽力修复它但没有成功:( git-rebase <A_SHA1>似乎根本不起作用。目前只有两个分支: masterfeature_branch

Is there even a way to make it look like this?有没有办法让它看起来像这样?

--A------B (master)
   \    / \
    C--D   E--F (feature_branch, HEAD)

Note that existing commits cannot be changed, so given:请注意,现有提交无法更改,因此给出:

...--α--A------B   <-- master
              / \
 ....--γ--C--D   E--F   <-- feature_branch (HEAD)

what you'll inevitably get from a rebase is, instead:你将不可避免地从 rebase 中得到的是:

            C'-D'  E'-F'  <-- feature_branch (HEAD)
           /    \ /
          /___---B'
         //
...--α--A------B   <-- master
              / \
 ....--γ--C--D   E--F   [abandoned]

You can then forcibly move master to point to B' instead of B so that you have:然后,您可以强制移动master指向B'而不是B这样您就可以:

            C'-D'  E'-F'  <-- feature_branch (HEAD)
           /    \ /
          /___---B'  <-- master
         //
...--α--A------B
              / \
 ....--γ--C--D   E--F   [abandoned]

It's now possible to ignore the presence of B , γ , C , and so on entirely and pretend that C' is C , for instance.例如,现在可以完全忽略BγC的存在并假装C'C Note that commit γ has become unreachable unless α and γ are really the same commit.请注意,除非αγ确实是同一个提交,否则提交γ已变得无法访问。

To achieve this using git rebase , you will want the somewhat-newfangled -r or --rebase-merges option:使用git rebase实现这一点,您将需要有点新奇的-r--rebase-merges选项:

git checkout feature_branch   # if needed - you've drawn a detached HEAD
git rebase -i -r --onto master <hash-of-γ>

after which you will need to delete commits such as α and A from the list of commits to be pick -ed, as these commits are all currently on feature_branch as well as on master , through merge commit B .之后,您需要从要pick的提交列表中删除诸如αA之类的提交,因为这些提交当前都在feature_branchmaster ,通过合并提交B (Note that -r was new in Git 2.18. The -r option uses the interactive machinery to instruct Git to re-perform merges, which is what we will do below.) (请注意, -r是 Git 2.18 中的新选项。 -r选项使用交互式机制来指示 Git重新执行合并,这就是我们将在下面执行的操作。)

Overall, though, it's probably easier to achieve this using separate git cherry-pick and git merge commands:不过,总的来说,使用单独的git cherry-pickgit merge命令可能更容易实现这一点:

git checkout --detach <hash-of-A>    # note: master~1 probably finds commit A
git cherry-pick <hash-of-C>          # make C'
git cherry-pick <hash-of-D>          # make D'
git merge --no-ff <hash-of-A>        # make new merge B'
git branch -f master HEAD            # forcibly update master now
git cherry-pick feature_branch~2     # make E'
git cherry-pick feature_branch~1     # make F'
git checkout -B feature_branch       # forcibly move feature_branch and re-attach HEAD

If master~1 does identify commit A , you can use that in place of each literal hash here, and in that case, master^2^ will identify commit C and master^2 will identify commit D , so you can use that in place of those two literal hash IDs.如果master~1确实标识了提交A ,您可以使用它代替此处的每个文字哈希,在这种情况下, master^2^将标识提交C并且master^2将标识提交D ,因此您可以使用它这两个文字哈希 ID 中的一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM