我希望在git rebase -i
期间获得有关当前编辑的提交的原始信息,但HEAD会引用不同的提交哈希。我如何引用原始提交?
$ git rebase -i upstream
(选择“编辑”进行提交)
[detached HEAD befa32f] Previous commit message
1 file changed, 121 insertions(+), 1 deletion(-)
rewrite README.md (100%)
Stopped at 9a1e25391e5a53965c80dc69e1285dba7c59f893... Current commit message
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
现在我想引用9a1e25391e5a53965c80dc69e1285dba7c59f893
但是HEAD有不同的哈希和不同的属性,虽然它似乎是相同的提交:
$ cat .git/HEAD
1414539371fe6b122d5f326bc7b344eea761dc50
这是从哪里来的,如何引用原始提交?
答案 0 :(得分:5)
对于它的价值,根据定义HEAD
总是“当前提交” - 或许更准确地说“当前提交是任何HEAD
说它是“。
最多“正常”时间,HEAD
包含对分支名称的引用:例如,如果您cat .git/HEAD
(或在文件查看器或编辑器中打开它),您将看到{{ 1}}或ref: refs/heads/master
,取决于您所在的分支。在这种情况下,您在命名分支上,当前提交是该分支的提示。 1
如果你使用ref: refs/heads/develop
或给git checkout --detach
原始提交SHA-1,另一方面,git会让你进入“分离的HEAD”模式。虽然这听起来像是18世纪法国大革命的场景,但它只是意味着git checkout
直接指向原始的SHA-1。在这种情况下,SHA-1是当前提交。
当您运行HEAD
并让它停止提交时(通过将处置设置为git rebase -i
),rebase将使您处于“分离的HEAD”模式,使用当前的commit-a.k.a。 edit
- 您现在可以编辑的提交。此时,您可以对树进行一些更改并执行HEAD
,例如:您对树所做的更改然后git add
现在位于暂存区域中。如果您接下来要做的是add
,那么git会创建一个新的提交,其父级与当前提交的父级相同:
git commit --amend
请注意,在 old <-- HEAD before `git commit --amend`
/
...--o
\
new <-- HEAD after `git commit --amend`
之后,git commit --amend
仍然是“当前提交”(根据定义),它不再是您要更改的提交(上面HEAD
)。
目前没有一种正确的方法可以通过名称来引用old
的SHA-1,但有几种方法可以找到它:例如,old
将显示提交可达来自git log --graph --decorate --oneline HEAD ORIG_HEAD
(您现在的位置,提交HEAD
)和new
(记录您第一次启动rebase时的位置:这不一定是提交ORIG_HEAD
但它的历史记录中会提交old
。
例如,在old
停止后,我添加了一个新文件,并使用rebase -i HEAD~2
进行了提交,结果如下:
git commit --amend
或者你可以依赖git内部(随着时间的推移而改变,所以无法保证这对你有用):
$ git log --graph --decorate --oneline HEAD ORIG_HEAD
* 9daa414 (HEAD) mod1, amended
| * bd49ea7 (master) mod2
| * f071da2 mod1
|/
* 28c4ee8 initial
这里,$ ls .git/rebase-merge
amend git-rebase-todo.backup onto
author-script head-name orig-head
done interactive patch
end message quiet
git-rebase-todo msgnum stopped-sha
具有我停止编辑时当前提交的SHA-1,因此:
rebase-merge/stopped-sha
作为Joseph K. Strauss noted in the comment below,查找$ git rev-parse rebase-merge/stopped-sha
f071da26a90f14945d89ccdeed3c278e9b499a2e
的最简单方法可能就是使用git的reflogs。由于我们刚刚创建了提交old
并移动了new
,因此旧提交HEAD
的SHA-1只是old
。当然,如果你做了几次提交(例如,几个HEAD@{1}
试图让它变得完美), 2 --amend
可能在old
下,{{1 }或更高。
请注意,此时,当我执行HEAD{2}
时,git会将剩余的项目(位于上述HEAD@{3}
输出中的git rebase --continue
)应用于当前{{ 1}}。如果一切顺利,那么rebase-merge/git-rebase-todo
做的最后一件事就是将当时的当前分支(在ls
中,在这种情况下包含HEAD
)重新指向最尖端的提交它制作,然后恢复rebase
的间接引用状态,以便我现在处于分支rebase-merge/head-name
的新提示:
refs/heads/master
1 或者,作为特殊情况,如果HEAD
包含对分支的引用但分支尚不存在,则说您处于“未出生的分支” 。在这种情况下,存在 no 当前提交,但是当您进行新提交时,它将是新的,现在出生的分支的初始提交。通常,人们仅在master
之后在新存储库中创建第一个提交时才会看到此信息。但是,在git 1.7.2及更高版本中,使用$ git rebase --continue
Successfully rebased and updated refs/heads/master.
创建了一个新的未出现的分支,这样您就可以将新的历史记录与现有存储库中的现有历史记录无关。
2 我不能代替其他任何人,但我一直这样做 。 : - )