如何在保留其更改的同时从Git存储库中删除选定的提交日志条目?


241

我想从线性提交树中删除选定的提交日志条目,以使这些条目不会显示在提交日志中。

我的提交树看起来像:

R--A--B--C--D--E--HEAD

我想删除B和C条目,以便它们不显示在提交日志中,但应保留从A到D的更改。也许通过引入单个提交,使B和C变为BC,树就看起来像。

R--A--BC--D--E--HEAD

或者,理想情况下,在A直接到达D之后。D'代表从A到B,B到C以及C到D的变化。

R--A--D'--E--HEAD

这可能吗?如果是,如何?

这是一个相当新的项目,因此到目前为止没有分支机构,因此也没有合并。


@ xk0der:“ commits”在这里是正确的术语。rebase可能会删除旧的/创建新的提交。我不知道“提交日志条目”是什么意思。
jfs 2012年

@JFSebastian我没有看到“提交日志”的问题-所有提交的日志。我想从日志中删除一些条目-同时保留实际更改(提交)。
xk0der 2012年

@ xk0der:git commits是内容可寻址的,即,如果您更改了commit中的任何内容,例如其日志消息;您创建一个新的提交。您可以在没有git的情况下阅读git的提交并亲自查看
jfs 2012年

@JFSebastian-感谢您的链接-我知道-但是这种技术性真的改变了我所面临的问题以及提出的方式吗?我猜不会。最后:我想删除“提交日志消息”-而不删除“提交更改”-请重新阅读我的问题-特别是第二段。要添加更多内容,请git log显示“提交日志” git-scm.com/docs/git-log。我想删除该日志中的两个条目-而不是更改。
xk0der 2012年

Answers:


273

git-rebase(1)正是这样做的。

$ git rebase -i HEAD~5

git awsome-ness [git rebase --interactive]包含一个示例。

  1. 不要git-rebase在公共(远程)提交上使用。
  2. 确保您的工作目录是干净的(commitstash当前更改)。
  3. 运行上面的命令。它启动您的$EDITOR
  4. 更换pickCD通过squash。它将C和D融合到B中。如果要删除提交,则只需删除其行即可。

如果您迷路了,请键入:

$ git rebase --abort  

感谢您的快速答复。那么,我是否结帐A并重新设置基准,例如git rebase -i D [A]
xk0der 2009年


3
我们如何在远程回购上做到这一点?
Eray

6
@Eray:只是push -f您的更改。如果您不是一个人工作,请不要这样做。
jfs

2
@ ripper234:我已经修复了指向git-rebase博客文章的手动和回溯机器的链接。
jfs

75
# detach head and move to D commit
git checkout <SHA1-for-D>

# move HEAD to A, but leave the index and working tree as for D
git reset --soft <SHA1-for-A>

# Redo the D commit re-using the commit message, but now on top of A
git commit -C <SHA1-for-D>

# Re-apply everything from the old D onwards onto this new place 
git rebase --onto HEAD <SHA1-for-D> master

这也起作用,并帮助我了解什么是软重置。当然,“最佳”答案也是正确且简短的,但也感谢您的回答。
cgp 2012年

41

这是一种仅知道您要删除的提交ID的删除特定提交ID的方法。

git rebase --onto commit-id^ commit-id

请注意,这实际上删除了由提交引入的更改。


7
此命令中额外的HEAD将导致重新整理以“分离的HEAD”完成,这是不希望的。应该忽略它。
冷淡,

3
这将还原我的commit-id中引入的更改,OP希望保留所做的更改,只是挤压提交。
CB Bailey

1
-1,因为它不执行OP要求的操作(而是破坏了他明确想要保留的内容)。
埃米尔·斯特尔克

1
尽管它不能满足OP的要求,但正是我所需要的,因此+1是有用的答案。
Edvins

20

扩展JF塞巴斯蒂安的答案:

您可以使用git-rebase轻松地对提交历史进行各种更改。

运行git rebase --interactive后,您将在$ EDITOR中得到以下内容:

pick 366eca1 This has a huge file
pick d975b30 delete foo
pick 121802a delete bar
# Rebase 57d0b28..121802a onto 57d0b28
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit

您可以移动行以更改提交的顺序,也可以删除行以删除该提交。或者,您可以添加命令以将两个提交合并(压缩)为单个提交(先前的提交是上述提交),编辑提交(已更改的内容)或重新编写提交消息。

我认为选择只是意味着您想不考虑该承诺。

(示例从这里开始



3

还有一种方法

git rebase -i ad0389efc1a79b1f9c4dd6061dca6edc1d5bb78a (C's hash)
and
git push origin master  -f

选择要用作基础的哈希,上面的命令应使其具有交互性,以便可以压缩所有顶部消息(您需要保留最旧的消息)


2

通过从A的SHA1创建另一个分支并挑选所需的更改,我发现此过程更安全,更容易理解,因此我可以确保对新分支的外观感到满意。之后,很容易删除旧分支并重命名新分支。

git checkout <SHA1 of A>
git log #verify looks good
git checkout -b rework
git cherry-pick <SHA1 of D>
....
git log #verify looks good
git branch -D <oldbranch>
git branch -m rework <oldbranch>

如果这样做,您也会丢失E提交,不是吗?据我了解,您删除master并将重做重命名为master(考虑到ABCDE流是master分支)。
Renan Bandeira

1

刚刚收集了所有人的答案:( git plz的新手仅供参考)

git rebase删除所有提交

git日志

-first check from which commit you want to rebase

git rebase -i HEAD〜1

-Here i want to rebase on the second last commit- commit count starts from '1')
-this will open the command line editor (called vim editor i guess)

然后屏幕将如下所示:

选择0c2236d添加了新行。

将2a1cd65..0c2236d重新设置为2a1cd65(1个命令)

命令:

p,选择=使用提交

r,reword =使用提交,但编辑提交消息

e,编辑=使用提交,但停止进行修改

s,squash =使用提交,但可以合并到先前的提交中

f,fixup =类似于“ squash”,但丢弃此提交的日志消息

x,exec =使用shell运行命令(其余部分)

d,drop =删除提交

这些行可以重新排序;它们从上到下执行。

如果您在此处删除一行,那将丢失。

但是,如果删除所有内容,则重新定位将中止。

注意,空提交被注释掉了~~









在这里根据您的需要更改第一行(使用上面列出的命令,即“ drop”以删除提交等。)完成编辑后,按“:x”以保存并退出编辑器(仅适用于vim编辑器)

然后

git推

如果显示问题,那么您需要强行将更改推送到远程(非常重要:如果您在团队中工作,请不要强行推送)

git push -f起源


-1

您可以为此使用git cherry-pick。'chery-pick'将提交到现在的分支上。

然后做

git rebase --hard <SHA1 of A>

然后应用D和E提交。

git cherry-pick <SHA1 of D>
git cherry-pick <SHA1 of E>

这将跳过B和C提交。话虽这么说,否则如果没有B,就不可能将D提交应用于分支,所以YMMV。


2
OP希望合并B,C,D提交,而不是删除其更改。
jfs

3
我想你的意思是reset --hard,不是rebase --hard(不存在)
Mauricio Scheffer'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.