我使用git来跟踪我们的开发团队所做的更改,并将其提交到我们的中央cvs样式的存储库中。由于它的cvs,它跟踪文件而不是提交,因此有时很难确切地说出哪些文件构成了bug补丁的完整补丁。我刚刚遇到一个并做了以下事情:
1)拖曳,检查CVS日志并将它们作为完整补丁提交给git
A--B--C--D
2)发现另一个文件更改实际上是故障单(B),因此我将当前分支重置为B
git reset --soft <sha1 ID for commit B>
3)我复制更改,并将其附加到提交(B)
git commit --amend
4)令我惊讶的是,树现在读了
A--B
仅在工作树中提交(C)和(D)。他们的详细信息已从日志中删除,我认为我无法取回它们。我哪里做错了?我唯一的选择是在(D)之上进行额外的提交,并且知道它真的是(B)的一部分吗?
答案 0 :(得分:14)
你的意思是修改,而不是附加,对吗?为方便起见,我假装这是在一个名为master的分支上。这就是您的存储库现在的样子:
A---B' (master)
\
\-B---C---D
Git提交明确依赖于他们的父母 - 在不同父级之上的相同补丁是不同的提交。
您可以通过几种方式恢复以前的位置。以前的位置有一个很好的速记,您可以使用它直接检查或创建分支:
git checkout master@{1}
git branch oldmaster master@{1}
这是假设它是先前的第一个位置。它可能是第二个(master@{2}
)...或者如果你知道它何时,你可以使用master@{7:35}
或master@{23.hours.ago}
。有关这些表单的摘要,请参阅man git-rev-parse
(online here)的“指定修订”部分。
如果您不确定如何操作,请尝试
git reflog show master
这将为您提供master
之前位置的列表,您应该能够从描述中了解您想要的位置(或者尝试一些)。您只需从列表中复制哈希值,然后使用上面的git checkout
或git branch
。
警告:编辑历史记录是一个坏主意,如果它已经发布 - 在这种情况下,您应该只是提交修复程序。是的,将它分成存储库中的两个提交是很难看的,但是其他用户必须能够相信他们在公共存储中看到的内容不会改变!
也就是说,要进行这种特殊的历史编辑,你需要交互式变换:
git rebase -i master~4 master
master~4
表示在master的提示之前提交四次提交。你可以在这里使用你想要的任何形式 - 也许它是另一个分支,也许是提交哈希 - 无论什么都有效。
这将在编辑器中打开您正在玩的提交列表:
pick <hash-A> <message-A>
pick <hash-B> <message-B>
pick <hash-C> <message-C>
pick <hash-D> <message-D>
# Rebase <hash-A^>..<hash-D> onto <hash-A^>
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
注释掉的帮助文本非常明显。在这种情况下,您希望在提交B的行上将“选择”更改为“编辑”,保存并退出。 rebase将启动,并在应用B
后允许您进行更改后暂停。您将执行所需操作,添加,使用git commit --amend
,然后git rebase --continue
。它将适用C
和D
,您将完成。如果中间出现任何问题,请使用git rebase --abort
返回到您开始的位置。
重新定位可能有点吓人 - 例如,不要意外删除该列表中的行!如果您对此感到不满意,最好大量使用gitk
和备份分支名称。
答案 1 :(得分:1)
4)令我惊讶的是,树现在读了
A - 乙的
实际上日志(历史记录)看起来像这样
A - B'
因为提交与不同。情况如下:
A---B' <-- master <--- HEAD \ \--B---C---D
提交链“B --- C --- D”(原始B)看起来丢失了,因为没有引用指向D.你的分支现在指向提交B'(修改提交B)。你仍然可以通过reflog访问D;它会是HEAD @ {2}我想......
我哪里出错?
您应该使用“git rebase --interactive
”,将提交B旁边的“选择”更改为“编辑”,然后在那里压缩补丁。
那,或者使用Git之上的补丁管理界面之一,如StGIT或Guilt。
他们的详细信息已从日志中消失,我认为我无法取回它们。
查看 reflog ,即“git reflog
”或“git log -g
”。在那里你应该看到你的“丢失”提交。
HTH