如何只挑选特定文件的更改?

871
如果我想将仅对某个提交中的部分文件进行更改的更改合并到一个Git分支中,该如何实现呢?
假设名为“stuff”的Git提交对文件A、B、C和D进行了更改,但我只想将“stuff”对文件A和B的更改合并。这听起来像是git cherry-pick的工作,但cherry-pick只知道如何合并整个提交,而不是文件的子集。

如果git gui可用,那我会像Cascabel一样操作。如果不行的话,Tyrone Wilson的方法对于精细选择变更是不错的选择。 - undefined
15个回答

7
我找到了另一种方法,可以防止在cherry-pick时出现任何冲突合并,我认为这种方法相当容易记住和理解。由于你实际上不是在cherry-pick一个提交,而是其中的一部分,所以你需要先拆分它,然后创建一个符合你需求的提交,并将其cherry-pick。
首先从你想要拆分的提交创建一个分支并切换到该分支:
$ git checkout COMMIT-TO-SPLIT-SHA -b temp

然后撤销之前的提交:

$ git reset HEAD~1

接着添加你想要挑选的文件/更改:

$ git add FILE

并提交它:

$ git commit -m "pick me"

请注意提交哈希值,我们称其为PICK-SHA并返回到您的主分支,例如master,并强制进行检出:

$ git checkout -f master

并挑选出该提交:

$ git cherry-pick PICK-SHA

现在您可以删除临时分支:

$ git branch -d temp -f

5

您可以使用:

git diff <commit>^ <commit> -- <path> | git apply

符号<commit>^表示<commit>的(第一个)父提交。所以,这个diff命令选择在提交<commit>中对<path>所做的更改。
注意,这不会像git cherry-pick一样立即提交任何内容。如果你希望这样做,你需要执行以下操作:
git add <path>
git commit

你可以指定任何有效范围,如果结果不适用,则可以选择使用 -3--3way 开关进行三方合并:... | git apply --3way - voiger

2

再自动化一点:

#!/usr/bin/env bash

filter_commit_to_files() {
    FILES="$1"
    SHA="$2"
    git show "$SHA" -- $FILES | git apply --index -
    git commit -c "$SHA"
}

使用示例:

filter_commit_to_files "file1.txt file2.txt" 07271c5e

我通过从这里复制并粘贴到我的shell中来定义它。你不需要使用Here文档


2
将一个分支合并到一个新的分支中(压缩),并删除不需要的文件:
git checkout master
git checkout -b <branch>
git merge --squash <source-branch-with-many-commits>
git reset HEAD <not-needed-file-1>
git checkout -- <not-needed-file-1>
git reset HEAD <not-needed-file-2>
git checkout -- <not-needed-file-2>
git commit

0

使用Patch标志结账

实现您所描述的功能的简单方法是通过 --patch 结账。修改我在顶部提供的四个变量。脚本执行以下操作:

  1. 克隆包含您提交的分支(源分支)
  2. 检出您希望将文件移动到的分支(目标分支)
  3. 以所需的提交修订版检出源分支,提供补丁标志和文件的相对位置作为参数。
  4. 添加、提交、推送

这对我来说一直是最简单的方法。第三步确实会创建一个交互式 shell,但如果您想覆盖目标,则可以默认选择整个过程。

source_branch=branch_with_file_you_want
destination_branch=file_go_here
rev=757c47d4
relative_file_path=structures/serializers/node.py
message="Patching a file from $source_branch to $destination_branch"

git clone https://github.com/yourepo/app.git -b $source_branch $source_branch
cd $source_branch
git checkout $destination_branch
git checkout $rev --patch $source_branch $relative_file_path
git add $relative_file_path
git commit -m "$message"
git push

如果你的远程库是 GitLab,你可以使用 git push -o merge_request.create 命令来创建一个合并请求。

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