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

rwo*_*lst 161 git git-merge

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

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

pdp*_*pdp 187

已接受的答案已提到使用file.py.现在,有可能是在内容上--patchgit-add(1)不再适用于file.py.这种情况需要挑选一些变化并留下其他变化.因此,要完全控制使用--patch开关执行交互式合并:

$ git checkout --patch branch2 file.py
Run Code Online (Sandbox Code Playgroud)

手册页中的交互模式部分用于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
Run Code Online (Sandbox Code Playgroud)

split命令特别有用.

  • 这不是合并,不保留历史记录 (5认同)
  • 我们如何使用补丁同时使用合并工具?而不是关键的东西 (2认同)
  • 我不明白这如何回答这个问题;事实上,此方法仅在一次独立提交中对“file.py”从 **branch2** 到 **branch1** 进行选择性更改;当从 **branch1** 看到时,它不会保留 **branch2** 中 `file.py` 的提交历史记录。 (2认同)

Мат*_*нер 101

正如评论中所指出的,这在技术上并不是"合并",这就是下面的链接使用引号的原因.但是,我很少需要像其他海报所描述的那样复杂的东西,所以我认为如果不是一个适当的OP解决方案,这对OP来说是有用的.

看看这个页面:Git提示:如何从另一个分支"合并"特定文件它提供了最简单的方法,恕我直言.

基本上,将它应用于您的情况:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py
Run Code Online (Sandbox Code Playgroud)

简单易用,file.py现在在branch1中.

  • 很简单,但实际上并不是*合并*.它只是用分支2中的任何内容覆盖`file.py`. (83认同)
  • 这会保留提交历史吗? (3认同)
  • @Beez 不,请参阅 RM 的回答 (2认同)

小智 15

是否所有修改都file.pybranch2自己的提交中,与其他文件的修改分开?如果是这样,您可以简单地cherry-pick进行更改:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>
Run Code Online (Sandbox Code Playgroud)

否则,merge不超过单个路径操作...你还不如干脆创建一个git diff补丁file.py从变化branch2以及git apply它们branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch
Run Code Online (Sandbox Code Playgroud)


R.M*_*.M. 14

其他当前答案都不会实际"合并"文件,就像您使用merge命令一样.(最好它们会要求你手动选择差异.)如果你真的想利用来自共同祖先的信息进行合并,你可以按照git 的"高级合并"部分中的步骤进行操作.参考手册.

对于这个协议,我假设您想要将origin/master中的文件'path/to/file.txt'合并到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
Run Code Online (Sandbox Code Playgroud)

git merge-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
Run Code Online (Sandbox Code Playgroud)


小智 12

Git checkout--merge为此提供了一个选项

git checkout --merge branch2 file.py

使用此选项将重新创建冲突的合并。

否则,当发生新的合并时:

# Detach and overwrite file.py with content from branch2 
git checkout --detach
git checkout branch2 file.py

# Amend changes and switch back
git commit --amend --no-edit
git checkout -

# Merge the detached branch back in
git merge --no-commit -
Run Code Online (Sandbox Code Playgroud)


Mak*_*gan 10

我发现最让我头疼的解决方案是:

git checkout <b1>
git checkout -b dummy
git merge <b2>
git checkout <b1>
git checkout dummy <path to file>
git branch -D dummy
Run Code Online (Sandbox Code Playgroud)

path to file完成此操作后, in中的文件b2就是与b1.

  • 愚蠢的问题:为什么 `git checkout b2 &lt;path to file&gt;` 本身不简化为相同的东西? (2认同)
  • 为什么“git checkout b2 &lt;文件路径&gt;”中的“&lt;文件路径&gt;”不能像这里的“git checkout dummy &lt;文件路径&gt;”一样有效地实现这一点?(git 文档中的[`pathspec`](https://git-scm.com/docs/git-checkout#Documentation/git-checkout.txt-ltpathspecgt82308203) - 无法判断这是否是它的预期工作方式或不是。)(顺便说一句,[你必须“@”我](https://stackoverflow.blog/2010/01/16/new-improved-comments-with-reply/)我才能收到你已经通知的通知直接回复我。AIA 如果(可能)您已经知道并且很着急;感谢您的跟进。) (2认同)

Mar*_*n G 8

你可以stashstash pop文件:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop
Run Code Online (Sandbox Code Playgroud)

  • 这会使用branch2/file.py 的内容覆盖branch1/file.py,而不是进行合并,从而引发需要解决的合并冲突。 (5认同)

jth*_*ill 5

要仅合并来自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
Run Code Online (Sandbox Code Playgroud)

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

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

git checkout -B wip `git merge-base branch1 branch2`
Run Code Online (Sandbox Code Playgroud)

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

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"
Run Code Online (Sandbox Code Playgroud)

  • @cueedee 是的,如果您想要明确的每个文件历史记录,则必须构建它。您可以这样做,仅使用该文件的branch2历史记录创建一个并行分支,并将branch2重建为来自file.py分支的合并,实际上,这就是每个文件历史记录vcs必须在每个文件的后台执行的操作。 (2认同)