246

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

我的提交树看起来像:

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

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

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

4

9 回答 9

276

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

$ git rebase -i HEAD~5

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

  1. 不要git-rebase在公共(远程)提交上使用。
  2. 确保您的工作目录是干净的(commitstash您当前的更改)。
  3. 运行上面的命令。它启动您的$EDITOR.
  4. 替换pick之前CD之前squash。它将 C 和 D 融合到 B 中。如果你想删除一个提交,那么只需删除它的行。

如果您迷路了,请输入:

$ git rebase --abort  
于 2009-01-30T12:26:03.353 回答
76
# 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
于 2009-01-30T13:45:48.293 回答
41

这是一种删除特定提交 id 的方法,只知道您要删除的提交 id。

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

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

于 2010-09-13T23:32:01.567 回答
20

要扩展 JF Sebastian 的答案:

您可以使用 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

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

我认为选择只是意味着您想不理会该提交。

(示例来自这里

于 2010-03-27T00:23:57.387 回答
14

您可以在示例中以非交互方式删除B 和 C:

git rebase --onto HEAD~5 HEAD~3 HEAD

或象征性地,

git rebase --onto A C HEAD

注意B和C的变化不会在D;他们会消失的。

于 2009-05-09T19:49:26.680 回答
3

通过从 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>
于 2013-04-17T23:24:07.507 回答
3

还有一种方式,

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

选择你想用它作为基础的散列,上面的命令应该让它交互,这样你就可以压缩所有最重要的消息(你需要留下最旧的)

于 2015-04-17T16:59:08.947 回答
1

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

git rebase 删除任何提交

混帐日志

-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 = like "squash", 但丢弃这个提交的日志信息

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

d, drop = 删除提交

#

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

#

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

#

但是,如果您删除所有内容,rebase 将被中止。

#

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

~~~~~~~~~
_
_
_
_
_
_
_
_

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

进而

git 推送

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

git push -f 原点

于 2017-10-05T14:55:58.033 回答
-1

您可以为此使用 git cherry-pick 。'cherry-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。

于 2009-02-02T23:47:42.350 回答