如何在git rebase期间引用当前编辑的提交的原始文件?

时间:2015-02-01 20:13:50

标签: git git-rebase

我希望在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

这是从哪里来的,如何引用原始提交?

1 个答案:

答案 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 我不能代替其他任何人,但我一直这样做 。 : - )