如何仅选择对某些文件的更改?
如果我想将仅对特定提交中更改的某些文件所做的更改合并到 Git 分支中,其中包括对多个文件的更改,如何实现?
假设名为 stuff
的 Git 提交对文件 A
、B
、C
和 D< /code> 但我只想合并
stuff
对文件 A
和 B
的更改。这听起来像是 gitcherry-pick 的工作,但 cherry-pick 只知道如何合并整个提交,而不是文件的子集。
If I want to merge into a Git branch the changes made only to some of the files changed in a particular commit which includes changes to multiple files, how can this be achieved?
Suppose the Git commit called stuff
has changes to files A
, B
, C
, and D
but I want to merge only stuff
's changes to files A
and B
. It sounds like a job for git cherry-pick
but cherry-pick
only knows how to merge entire commits, not a subset of the files.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
我会使用cherry-pick -n(
--no-commit
)来完成它,它可以让您在提交之前检查(和修改)结果:如果绝大多数修改是您不想要的,您可以将所有内容重置回来,而不是检查各个路径(中间步骤),然后添加您想要的内容:
I'd do it with
cherry-pick -n
(--no-commit
) which lets you inspect (and modify) the result before committing:If the vast majority of modifications are things you don't want, instead of checking out individual paths (the middle step), you could reset everything back, then add in what you want:
其他方法对我不起作用,因为提交有很多更改并且与许多其他文件发生冲突。我想出的只是
它实际上并没有
添加
文件或为您进行提交,因此您可能需要跟进或者如果您想跳过添加,您可以使用 < code>--cached 参数到
git apply
您也可以对整个目录执行相同的操作
The other methods didn't work for me since the commit had a lot of changes and conflicts to a lot of other files. What I came up with was simply
It doesn't actually
add
the files or do a commit for you so you may need to follow it up withOr if you want to skip the add you can use the
--cached
argument togit apply
You can also do the same thing for entire directories
我通常将
-p
标志与来自其他分支的 git checkout 一起使用,我发现这比我遇到的大多数其他方法更容易、更精细。原则上:
示例:
然后您会看到一个对话框,询问您想要在“blob”中进行哪些更改,这几乎适用于您可以进行的连续代码更改的每个块每个代码块的信号
y
(是)n
(否)等。-p
或patch
选项适用于 git 中的各种命令,包括git stash save -p
,它允许您选择您想要的内容 当我做了很多工作并且想将其分离出来并使用 git add -p 提交更多基于主题的提交并选择我想要的内容时,我有时会使用这种技术每次提交:)
I usually use the
-p
flag with a git checkout from the other branch which I find easier and more granular than most other methods I have come across.In principle:
example:
You then get a dialog asking you which changes you want in "blobs" this pretty much works out to every chunk of continuous code change which you can then signal
y
(Yes)n
(No) etc for each chunk of code.The
-p
orpatch
option works for a variety of commands in git includinggit stash save -p
which allows you to choose what you want to stash from your current workI sometimes use this technique when I have done a lot of work and would like to separate it out and commit in more topic based commits using
git add -p
and choosing what I want for each commit :)情况:
您在自己的分支上,比如说
master
,并且您在任何其他分支上都有提交。您必须从该特定提交中仅选择一个文件。方法:
第1步:在所需分支上结帐。
第 2 步:确保您已复制所需的提交哈希。
第 3 步: 现在,您已在所需分支上对所需文件进行了更改。您只需要添加并提交它们。
The situation:
You are on your branch, let's say
master
and you have your commit on any other branch. You have to pick only one file from that particular commit.The approach:
Step 1: Checkout on the required branch.
Step 2: Make sure you have copied the required commit hash.
Step 3: You now have the changes of the required file on your desired branch. You just need to add and commit them.
也许这种方法相对于 Jefromi 的优势答案是你不必记住git重置的行为是正确的:)
Perhaps the advantage of this method over Jefromi's answer is that you don't have to remember which behaviour of git reset is the right one :)
Cherry pick 是从特定的“提交”中挑选更改。最简单的解决方案是选择某些文件的所有更改,方法是使用
示例:
来源和完整解释http://jasonrudolph.com/blog /2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/
更新:
使用此方法,git 不会合并文件,它只会覆盖目标分支上所做的任何其他更改。您需要手动合并更改:
Cherry pick is to pick changes from a specific "commit". The simplest solution is to pick all changes of certain files is to use
In example:
Sources and full explanation http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/
UPDATE:
With this method, git will not MERGE the file, it will just override any other change done on the destination branch. You will need to merge the changes manually:
为了完整起见,对我来说最有效的是:
它完全符合OP的要求。它会在需要时解决冲突,与
merge
的做法类似。它会git add
但不会git commit
您的新更改,因此请检查您的git status
。For the sake of completness, what works best for me is:
It does exactly what OP wants. It does conflict resolution when needed, similarly how
merge
does it. It doesgit add
but notgit commit
your new changes, so check yourgit status
.有时,使用签出从提交中获取特定文件可能会更容易。在我看来,它给了你更多的控制权。
我会这样做:
然后取消必要的更改以适应代码并在提交之前对其进行测试。如果一切按预期进行,则提交。
Sometimes it could be easier to use checkout to bring specific files from a commit. In my opinion it gives you more control.
I would do it like this:
Then unstage the necessary changes to adapt the code and test it before do commit. If everything works as expected, then commit.
我会挑选所有内容,然后执行以下操作:
然后我会恢复我不想要的更改,然后进行新的提交。
I would just cherry-pick everything, then do this:
Then I would revert the changes I don't want, then make a new commit.
使用 git merge --squashbranch_name ,这将从其他分支获取所有更改,并为您准备提交。
现在删除所有不需要的更改并保留您想要的更改。并且 git 不会知道有合并。
Use
git merge --squash branch_name
this will get all changes from the other branch and will prepare a commit for you.Now remove all unneeded changes and leave the one you want. And git will not know that there was a merge.
我找到了另一种方法,可以防止在挑选时出现任何冲突的合并,在我看来,这种方法很容易记住和理解。由于您实际上不是在挑选提交,而是其中的一部分,因此您需要先将其拆分,然后创建一个适合您的需求的提交并挑选它。
首先从要拆分的提交创建一个分支并签出它:
然后恢复以前的提交:
然后添加要挑选的文件/更改:
并提交它:
记下提交哈希,我们将其称为 PICK-SHA 并继续回到你的主分支,master 例如强制签出:
并挑选提交:
现在你可以删除临时分支:
I found another way which prevents any conflicting merge on cherry-picking which IMO is kind of easy to remember and understand. Since you are actually not cherry-picking a commit, but part of it, you need to split it first and then create a commit which will suit your needs and cherry-pick it.
First create a branch from the commit you want to split and checkout it:
Then revert previous commit:
Then add the files/changes you want to cherry-pick:
and commit it:
note the commit hash, let's call it PICK-SHA and go back to your main branch, master for example forcing the checkout:
and cherry-pick the commit:
now you can delete the temp branch:
您可以使用:
符号
^
指定
的(第一个)父级。因此,此 diff 命令会选择提交
中对
所做的更改。请注意,这还不会提交任何内容(如 gitcherry-pick 所做的那样)。所以如果你想要这样,你必须这样做:
You can use:
The notation
<commit>^
specifies the (first) parent of<commit>
. Hence, this diff command picks the changes made to<path>
in the commit<commit>
.Note that this won't commit anything yet (as
git cherry-pick
does). So if you want that, you'll have to do:将一个分支合并到新分支(squash)并删除不需要的文件:
Merge a branch into new one (squash) and remove the files not needed:
自动化程度更高:
示例用法:
我通过从这里复制并粘贴到我的 shell 中来定义它。您不需要此处文档。
Automating a bit more:
Example usage:
I define it via copy and paste from here right into my shell. You don't need a here document.
使用补丁标志签出
完成您所描述的内容的一种简单方法是通过签出 --patch。修改我在顶部提供的四个变量。该脚本执行以下操作:
这对我来说一直是最简单的方法。步骤#3确实创建了一个交互式shell,但是如果你想破坏目标,你可以默认选择整个事情。
Checkout with Patch Flag
An easy way to accomplish what you are describing is through a checkout --patch. Modify the four variables I provided at the top. The script does the following:
This has always been the easiest method for me. Step #3 does create an interactive shell though, but you can default option the entire thing if you want to clobber the destination.