如果我想将仅对特定提交中更改的部分文件(包括对多个文件的更改)进行的更改合并到Git分支中,如何实现这一点?
假设名为stuff的Git提交对文件A、B、C和D进行了更改,但我只想将stuff的更改合并到文件A和B。这听起来像Git cherry-pick的工作,但cherry pick只知道如何合并整个提交,而不是文件的子集。
如果我想将仅对特定提交中更改的部分文件(包括对多个文件的更改)进行的更改合并到Git分支中,如何实现这一点?
假设名为stuff的Git提交对文件A、B、C和D进行了更改,但我只想将stuff的更改合并到文件A和B。这听起来像Git cherry-pick的工作,但cherry pick只知道如何合并整个提交,而不是文件的子集。
当前回答
使用修补程序标志签出
完成您所描述内容的一个简单方法是通过签出补丁。修改我在顶部提供的四个变量。脚本执行以下操作:
克隆包含提交的分支(源分支)签出要将文件移动到的分支(目标分支)在所需的提交版本签出源分支,提供补丁标志和文件的相对位置作为参数。添加、提交、推送
对我来说,这一直是最简单的方法。步骤#3确实创建了一个交互式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,如果您需要MR,可以使用git push-o merge_request.create
其他回答
我会选择一切,然后这样做:
git reset --soft HEAD^
然后我会还原我不想要的更改,然后进行新的提交。
使用gitmerge--squashbranch_name,这将从其他分支获取所有更改,并为您准备提交。现在删除所有不需要的更改并保留所需的更改。git不会知道有合并。
将分支合并为新分支(挤压)并删除不需要的文件:
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
与Jefromi的答案相比,这种方法的优势可能在于您不必记住git重置的哪个行为是正确的:)
# Create a branch to throw away, on which we'll do the cherry-pick:
git checkout -b to-discard
# Do the cherry-pick:
git cherry-pick stuff
# Switch back to the branch you were previously on:
git checkout -
# Update the working tree and the index with the versions of A and B
# from the to-discard branch:
git checkout to-discard -- A B
# Commit those changes:
git commit -m "Cherry-picked changes to A and B from [stuff]"
# Delete the temporary branch:
git branch -D to-discard
我会使用cherry-pick-n(--no-commit)来完成,它允许您在提交之前检查(和修改)结果:
git cherry-pick -n <commit>
# unstage modifications you don't want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD <path>
# commit; the message will have been stored for you by cherry-pick
git commit
如果绝大多数修改都是您不想要的,那么您可以重新设置所有内容,然后添加您想要的内容,而不是检查各个路径(中间步骤):
# unstage everything
git reset HEAD
# stage the modifications you do want
git add <path>
# make the work tree match the index
# (do this from the top level of the repo)
git checkout .