如何撤消多个“;git提交——修改;还是为了让每一次修改都有所不同?
我错做了100多件事。如何将它们转换为常规提交?或者至少要获得每次修改提交都有差异的git日志? 如果现在运行如何撤消多个“;git提交——修改;还是为了让每一次修改都有所不同?,git,commit,undo,git-amend,Git,Commit,Undo,Git Amend,我错做了100多件事。如何将它们转换为常规提交?或者至少要获得每次修改提交都有差异的git日志? 如果现在运行gitk或git log-p,我一次只能看到所有修改提交的差异。我可以看到所有的hash,但只能使用reflog。我还可以看到git diff amend_hash1 amend_hash2的不同之处,但在gitk或git log-p中看不到。尽管它们在.git/logs/refs/heads/master和.git/logs/HEAD中链接正确,但它们跳过了这些修改 我刚刚运行了git
gitk
或git log-p,我一次只能看到所有修改提交的差异。我可以看到所有的hash,但只能使用reflog。我还可以看到git diff amend_hash1 amend_hash2
的不同之处,但在gitk
或git log-p
中看不到。尽管它们在.git/logs/refs/heads/master
和.git/logs/HEAD
中链接正确,但它们跳过了这些修改
我刚刚运行了git commit--amend
100次,每100次修改一次。然后,当我运行git commit without amend时,我得到了所有100个更改的一个大提交
我发现了如何只撤销一个修改提交…它们都在进行修改的回购协议的reflog中,并且它们都是完全普通的提交,因此您可以例如,
git show
查看它们所做的更改,并git cherry pick
将它们挑选出来以获得这些更改等等。查看git reflog
文档,并查看例如.git/logs/refs/heads/master
中的内容
这些提交在gitk中显示为一个提交- 我怀疑实际发生的情况是,您已经将100个提交压缩在一起,可能是使用了
git merge--squash
。幸运的是,这比实际修改100次提交要容易得多(这是非常不寻常的)。我们需要找到分支机构的原始负责人
如果运气好,ORIG_HEAD
仍然设置为分支的原始头。使用git log ORIG_HEAD检查
否则,在进行挤压合并之前,请使用查找分支尖端。你在找这样的东西
a83ad6b (master) HEAD@{1}: commit: Squashed commit of the following:
78c06ed HEAD@{2}: checkout: moving from feature to master
6493a4c HEAD@{2}: commit (amend): The log message
a2a99ea HEAD@{3}: commit: The log message
a83ad6b
是新的压缩提交78c06ed
是分支的原始未校准尖端
找到原始提交后,将分支移回原始提交
git branch -f <commit id>
a2a99ea
是原始的、未经修改的提交6493a4c
是新修订的提交
通常,您应该能够grep forcommit(amend)
,并使用前面的reflog和相同的commit消息。然而,这并不能保证。例如,在提交和修改之间可能存在签出和拉取
0742a3a HEAD@{111}: commit (amend): chore: Add a simple monitoring process.
b71620d HEAD@{112}: pull: checkout e29402b1fda83664cf17782b1a34e2bb4a77d44f: returning to refs/heads/master
b71620d HEAD@{113}: pull: checkout e29402b1fda83664cf17782b1a34e2bb4a77d44f: chore: Add a simple monitoring process.
e29402b HEAD@{114}: pull: checkout e29402b1fda83664cf17782b1a34e2bb4a77d44f
fab188c HEAD@{115}: commit: chore: Add a simple monitoring process.
或者修正可以更改提交消息
6493a4c HEAD@{2}: commit (amend): A different log message
a2a99ea HEAD@{3}: commit: The log message
我认为这可以用图片来解释,尽管我的ASCII艺术能力在几次修改后就耗尽了。诀窍是要认识到,git commit--amend
与没有--amend
的git commit
相比所做的是更改存储在新提交中的父散列
正常的git提交
将索引内容冻结到树中,并使用新树、您作为作者和提交者、日志消息以及当前提交作为新提交的父级进行新提交:
...--F--G <-- [you were here]
\
H <-- branch (HEAD) [you are here now]
和新提交J:
...--F--G--H--I--J <-- branch (HEAD)
然后,制作I
,除了I
的父项是F
而不是H
之外,我们照常制作:
G [you were here]
/
...--F--H [you were here too]
\
I <-- branch (HEAD)
H'
/
GH
| I
|/ J
...--F==K
|\ L
| M
ON
每个不同的提交都有您想要的树和消息。除了G
本身之外,这些提交中的每一个都有一个错误,那就是它有一个错误的父级:您希望G
有F
作为它的父级(它有),但您希望H
有G
作为它的父级(它没有)
这意味着您必须复制错误的提交。首先,我们将H
复制到H'
中,它的父级为G
,但使用与H
相同的树、消息和其他元数据:
G [you were here]
/
...--F--H [you were here too]
\
I <-- branch (HEAD)
H'
/
GH
| I
|/ J
...--F==K
|\ L
| M
ON
现在我们需要将I
复制到新的提交I'
。I'
的父项不是G
,而是H'
:
H'-I'
/
GH
| I
|/ J
...--F==K
|\ L
| M
ON
我们重复J
到J'
,使用I'
作为J'
的父级,依此类推,直到我们将每个“错误”提交复制到“正确”提交。然后,我们可以设置一个分支名称,以指向上次复制的提交:
H'-I'-J'-K'-L'-M'-N'-O' <-- repaired
/
GH
| I
|/ J
...--F==K
|\ L
| M
ON
这将创建一个新的分支名称repaired
,以保存新构建的链。修改后的提交是“常规”提交。照常作出的承诺与另一次修改的承诺之间没有真正的区别。你能用一个简短的例子解释一下你做了什么以及你想做什么或得到什么吗?这些提交在GitKaming 100提交中显示为一个提交,这是不寻常的。你把它们压扁了吗?那是完全不同的事情。能否显示您运行的确切命令?请添加您运行的确切命令以“修改”提交。@l0pan将只修改一次提交。你还跑了什么让它变成100?顺便说一句,这样做更好更安全。是的,我可以看到他们的哈希与reflog。但我想在gitk中或使用'git log-p'@l0pan来查看它们,而不知道您一次修改100次提交的具体操作,我无法告诉您如何恢复它们。我只是针对100次更改中的每一次运行'git commit--amend'100次。我没有运行合并。然后我在没有修正的情况下进行了提交,并在100人中获得了一次重大提交changes@l0pan最后一次不应该发生。请编辑您的问题以准确显示您运行的命令。最好是从您的终端复制和粘贴。您确定上次没有修改的-amend
git提交是否确实做了什么?如果没有阶段性的更改,那么基本上,git commit
是不可操作的。使用cherry pick
会很痛苦;它们都应该有正确的树,因此使用git提交树应该是无痛的。如果它们是普通的提交,那么为什么gitk
和git log-p
忽略它们呢?尽管它们在.git/logs/refs/heads/master
Reflog中链接正确,它们还是跳过了这些修改
H'-I'-J'-K'-L'-M'-N'-O' <-- repaired
/
GH
| I
|/ J
...--F==K
|\ L
| M
ON
parent=$hash # hash ID of commit G, onto which new chain will be built
while read tocopy; do
tree=$(git rev-parse $tocopy^{tree})
parent=$(git cat-file -p $tocopy | sed '1,/^$/d' |
git commit-tree -p $parent -t $tree)
done < $file_of_commits
git branch repaired $parent