我能否从另一个git提交中交互地选择文件块?

33

我正在寻找与

完全相同的行为。

git add -i -p

我想从一个(或部分)提交中建立我的工作目录,而不是从我的工作目录合成一个提交。该怎么做呢?

我的使用情况是,我有几个不同的特性被组合在一个单独的提交中,我想逐个测试它们。

使用cherry-pick -n并不是很满意,因为它留下了许多不需要的代码需要手动清理。 我只想挑选我想要测试的修改。


1
好的,真正的解决方案是拆分提交,这样你就不会被“所有不必要的代码”卡住,需要先删除。我认为最好使用cherry-pick,而不是git reset(总是有点危险)。 - sehe
当然我会分割提交,我只需要找出什么要分割(以及什么要丢弃)。 - krosenvold
4个回答

39

使用 cherry-pick -n 并不是很令人满意,因为它让我留下了清理所有不必要代码的麻烦。我真的只想选择我想测试的更改。

以前这项工作可能是一项棘手的工作,但随着 git checkout --patch 的出现,你现在可以有选择性地丢弃更改,类似于添加时的 git add -p


哦,这是一个好东西。正是我需要的。请注意,如果您的目标不是樱桃补丁的祖先,那么在您的目标提交之上重新定位/挑选提交可能是明智的选择。 - krosenvold
注意:这并不总是从提交中一致地选择更改,而是从某个文件状态中选择片段!(可能会覆盖/丢失其他后期更改) - kxr

11

您可以使用git reset --mixed HEAD^1来还原索引,然后使用git add -i选择您想要的块。

reset将把索引回滚到上一个提交(实际上是取消了HEAD所指向的提交),但不会影响工作树。现在,您可以暂存您需要的内容块,将它们提交并使用git reset --hard HEAD删除其余部分。


6
作为一个非常小的注释,git reset 的默认模式是 --mixed,因此您可以不需要使用该选项。 - Mark Longair

3

在Cameron Skinner出色的回答基础上,我稍微展开一下,以包括当你有一个带有多个提交的分支时,可能会有合并提交,可能会有很多“噪音”,而你只想从中挑选出非常特定的块进行 cherry-pick。(这正是今天发生在我身上的情况)

按照以下步骤进行操作:

git checkout source-branch
git checkout -b cherry-pick-branch # Gives you a new branch based on source-branch
git reset --mixed master

这将使你拥有一个分支,其中所有更改都在文件系统中,但没有提交/暂存。然后使用 git add -p 选择性地添加您想要暂存的部分,然后像平常一样提交和推送。


0
如果您不接受这个,请让我知道。

清除所有不必要的代码的繁琐工作

git cherry-pick -n ...         # Starting from clean status
git reset                      # unstage
git add -p / -i [<pathspec>…​]  # add hunks interactively
git restore .                  # wipe the rest (at root dir)

例如,如果您想合并未提交的更改或不想破坏时间戳,那么像这样使用git apply可能是一种更清洁的选项:

git show <commit> | tee _.patch
edit _.patch                    # strip unwanted hunks
git apply -3 _.patch

只要git cherry-pickgit apply没有直接支持-p)

注意:像git checkout / restore -p ...这样的方法不能一致地从特定提交中还原hunks,而是从某个文件状态中挑选部分-可能会丢失其他后续提交中的更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接