Git 用 rebase 改写历史
Git rewriting history with rebase
我目前在一个看起来像这样的分支上工作
--A------B (master)
/ \
----C--D E--F (feature_branch, HEAD)
我一直在尽力修复它,但没有成功:(
git-rebase <A_SHA1>
似乎根本不起作用。目前只有两个分支:master
和feature_branch
.
有没有办法让它看起来像这样?
--A------B (master)
\ / \
C--D E--F (feature_branch, HEAD)
请注意,无法更改现有提交,因此给出:
...--α--A------B <-- master
/ \
....--γ--C--D E--F <-- feature_branch (HEAD)
你将不可避免地从 rebase 中得到的是:
C'-D' E'-F' <-- feature_branch (HEAD)
/ \ /
/___---B'
//
...--α--A------B <-- master
/ \
....--γ--C--D E--F [abandoned]
然后您可以强行移动 master
以指向 B'
而不是 B
以便您拥有:
C'-D' E'-F' <-- feature_branch (HEAD)
/ \ /
/___---B' <-- master
//
...--α--A------B
/ \
....--γ--C--D E--F [abandoned]
现在可以完全忽略 B
、γ
、C
等的存在,并假装 C'
是 C
,例如。请注意,提交 γ
已变得无法访问,除非 α
和 γ
确实是相同的提交。
要实现此 使用 git rebase
,您需要 somewhat-newfangled -r
或 --rebase-merges
选项:
git checkout feature_branch # if needed - you've drawn a detached HEAD
git rebase -i -r --onto master <hash-of-γ>
之后,您需要从要进行 pick
编辑的提交列表中删除 α
和 A
等提交,因为这些提交目前都在 feature_branch
以及 master
,通过合并提交 B
。 (请注意 -r
是 Git 2.18 中的新内容。-r
选项使用交互式机制指示 Git 到 re-perform合并,这就是我们下面要做的。)
总体而言,使用单独的 git cherry-pick
和 git 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
如果 master~1
确实标识了提交 A
,您可以在此处使用它来代替每个文字散列,在这种情况下,master^2^
将标识提交 C
并且 master^2
将标识提交 D
,因此您可以使用它来代替这两个文字哈希 ID。
我目前在一个看起来像这样的分支上工作
--A------B (master)
/ \
----C--D E--F (feature_branch, HEAD)
我一直在尽力修复它,但没有成功:(
git-rebase <A_SHA1>
似乎根本不起作用。目前只有两个分支:master
和feature_branch
.
有没有办法让它看起来像这样?
--A------B (master)
\ / \
C--D E--F (feature_branch, HEAD)
请注意,无法更改现有提交,因此给出:
...--α--A------B <-- master
/ \
....--γ--C--D E--F <-- feature_branch (HEAD)
你将不可避免地从 rebase 中得到的是:
C'-D' E'-F' <-- feature_branch (HEAD)
/ \ /
/___---B'
//
...--α--A------B <-- master
/ \
....--γ--C--D E--F [abandoned]
然后您可以强行移动 master
以指向 B'
而不是 B
以便您拥有:
C'-D' E'-F' <-- feature_branch (HEAD)
/ \ /
/___---B' <-- master
//
...--α--A------B
/ \
....--γ--C--D E--F [abandoned]
现在可以完全忽略 B
、γ
、C
等的存在,并假装 C'
是 C
,例如。请注意,提交 γ
已变得无法访问,除非 α
和 γ
确实是相同的提交。
要实现此 使用 git rebase
,您需要 somewhat-newfangled -r
或 --rebase-merges
选项:
git checkout feature_branch # if needed - you've drawn a detached HEAD
git rebase -i -r --onto master <hash-of-γ>
之后,您需要从要进行 pick
编辑的提交列表中删除 α
和 A
等提交,因为这些提交目前都在 feature_branch
以及 master
,通过合并提交 B
。 (请注意 -r
是 Git 2.18 中的新内容。-r
选项使用交互式机制指示 Git 到 re-perform合并,这就是我们下面要做的。)
总体而言,使用单独的 git cherry-pick
和 git 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
如果 master~1
确实标识了提交 A
,您可以在此处使用它来代替每个文字散列,在这种情况下,master^2^
将标识提交 C
并且 master^2
将标识提交 D
,因此您可以使用它来代替这两个文字哈希 ID。