如何合并来自 Git 分支的特定文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18115411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 16:43:46  来源:igfitidea点击:

How to merge specific files from Git branches

gitgit-merge

提问by rwolst

I have 2 git branches branch1 and branch2 and I want to merge file.py in branch2 into file.py in branch1 and only that file.

我有 2 个 git 分支 branch1 和 branch2,我想将 branch2 中的 file.py 合并到 branch1 中的 file.py 并且只有那个文件。

In essence I just want to work on the file.py in branch1 but want to take advantage of the merge command. What is the best way to do this?

本质上,我只想处理 branch1 中的 file.py 但想利用合并命令。做这个的最好方式是什么?

回答by pdp

When content is in file.pyfrom branch2that is no longer applies to branch1, it requires picking some changes and leaving others. For full control do an interactive merge using the --patchswitch:

当内容file.py来自branch2不再适用于branch1 时,它需要选择一些更改并保留其他更改。要完全控制,请使用--patch开关进行交互式合并:

$ git checkout --patch branch2 file.py

The interactive mode section in the man page for git-add(1)explains the keys that are to be used:

手册页中的交互模式部分git-add(1)解释了要使用的键:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

The split command is particularly useful.

split 命令特别有用。

回答by Мати Тернер

Although not a mergeper se, sometimes the entire contents of another file on another branch are needed. Jason Rudolph's blog postprovides a simple way to copy files from one branch to another. Apply the technique as follows:

虽然本身不是合并,但有时需要另一个分支上另一个文件的全部内容。Jason Rudolph 的博客文章提供了一种将文件从一个分支复制到另一个分支的简单方法。应用该技术如下:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Now file.pyis now in branch1.

现在file.pybranch1 中

回答by R.M.

None of the other current answers will actually "merge" the files, as if you were using the merge command. (At best they'll require you to manually pick diffs.) If you actually want to take advantage of merging using the information from a common ancestor, you can follow a procedure based on one found in the "Advanced Merging" sectionof the git Reference Manual.

其他当前答案都不会实际“合并”文件,就好像您正在使用合并命令一样。(充其量他们会要求您手动选择差异。)如果您确实想利用来自共同祖先的信息进行合并,则可以按照基于git的“高级合并”部分中的程序进行操作参考手册。

For this protocol, I'm assuming you're wanting to merge the file 'path/to/file.txt' from origin/master into HEAD - modify as appropriate. (You don't have to be in the top directory of your repository, but it helps.)

对于此协议,我假设您希望将文件“path/to/file.txt”从 origin/master 合并到 HEAD - 根据需要进行修改。(您不必位于存储库的顶级目录中,但这会有所帮助。)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

git merge-fileshould use all of your default merge settings for formatting and the like.

git merge-file应该使用您所有的默认合并设置进行格式化等。

Also note that if your "ours" is the working copy version and you don't want to be overly cautious, you can operate directly on the file:

另请注意,如果您的“我们的”是工作副本版本并且您不想过于谨慎,则可以直接对文件进行操作:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt

回答by R.M.

Are all the modifications to file.pyin branch2in their own commits, separate from modifications to other files? If so, you can simply cherry-pickthe changes over:

所有对file.pyin的修改都在branch2他们自己的提交中,与对其他文件的修改分开吗?如果是这样,您可以简单地cherry-pick更改:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

Otherwise, mergedoes not operate over individual paths...you might as well just create a git diffpatch of file.pychanges from branch2and git applythem to branch1:

否则,merge不会在单个路径上运行......您不妨创建一个从和它们到git difffile.py更改补丁:branch2git applybranch1

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

回答by Martin G

You can stashand stash popthe file:

你可以stashstash pop文件:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

回答by jthill

To merge only the changes from branch2's file.py, make the other changes go away.

要仅合并来自 branch2 的更改file.py,请使其他更改消失。

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

Merge will never even look at any other file. You might need to '-f' the checkouts if the trees are different enough.

Merge 甚至不会查看任何其他文件。如果树足够不同,您可能需要“-f”结帐。

Note that this will leave branch1 looking as if everything in branch2's history to that point has been merged, which may not be what you want. A better version of the first checkout above is probably

请注意,这将使 branch1 看起来好像 branch2 历史记录中的所有内容都已合并,这可能不是您想要的。上面第一个结帐的更好版本可能是

git checkout -B wip `git merge-base branch1 branch2`

in which case the commit message should probably also be

在这种情况下,提交消息也应该是

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"

回答by Trac Nguyen

I am in same situation, I want to merge a file from a branch which has many commits on it on 2 branch. I tried many ways above and other I found on the internet and all failed (because commit history is complex) so I decide to do my way (the crazy way).

我处于同样的情况,我想从一个分支合并一个文件,该分支在 2 个分支上有很多提交。我尝试了很多上面和我在互联网上找到的其他方法,但都失败了(因为提交历史很复杂),所以我决定按我的方式做(疯狂的方式)。

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge

回答by Lucas Lima

What I've done is a bit manual, but I:

我所做的有点手动,但我:

  1. Merged the branches normally; Reverted the merge with revert;
  2. Checked out all my files to HEAD~1, that is, their state in the merge commit;
  3. Rebased my commits to hide this hackery from the commit history.
  1. 正常合并分支;恢复与revert;的合并
  2. 将我的所有文件检出到HEAD~1,即它们在合并提交中的状态;
  3. 重新调整我的提交以在提交历史记录中隐藏这个hackery。

Ugly? Yes. Easy to remember? Also yes.

丑陋的?是的。容易记住?也是。