如何将更改合并到单个文件,而不是合并提交?


382

我有两个分支(A和B),我想将来自分支A的单个文件与来自分支B的相应单个文件合并。



27
关于该其他帖子的大多数回复都与如何有选择地合并提交(而非文件)有关。这使所选答案不正确。问题仍然没有答案。


IMO,这个答案是正确的方法。 git diff branch_name > patch git apply patchstackoverflow.com/a/9473543/1091853
blamb

Answers:


630

我遇到了同样的问题。确切地说,我有两个分支,A并且B具有相同的文件,但在某些文件中具有不同的编程接口。现在f,独立于两个分支的接口差异的file方法已在分支中更改B,但更改对于两个分支都很重要。因此,我只需要将fbranch的B文件合并到branch的文件fA

如果我假设所有更改都在两个分支A和中提交,那么一个简单的命令已经为我解决了问题B

git checkout A

git checkout --patch B f

第一个命令切换到分支A,进入我要合并B文件版本的位置f。第二个命令f使用fHEADof 修补文件B。您甚至可以接受/丢弃补丁的单个部分。不必在B此处指定任何提交,而不必指定HEAD

社区编辑:如果文件fon B尚不存在A,则忽略该--patch选项。否则,您将获得“无更改”。信息。


10
这仅在您要更新文件时有效。如果要从分支B向分支A添加新文件怎么办?
Umair A. 2014年

25
@UmairAshraf,您应该可以通过删除--patch选项将新文件从B添加到A。
bbak 2014年

9
嗯...当我尝试这样做时,我收到消息“没有更改”,但是显然有更改。好的,我需要放在相关文件所在的文件夹中。编辑:这很可能是我在stackoverflow上看到的问题的最喜欢的解决方案:-D
bot_bot 2014年

2
我不得不用git checkout --patch B -- f它来工作。
user545424

8
只需添加一下,如果文件中有多个更改(大块)并且要暂存所有更改,则可以a在交互阶段按,而不是y每次都按。或使用git checkout B -- f命令代替。
德米特里·贡查

17

这是我在这些情况下的工作。这很麻烦,但对我来说很好。

  1. 根据您的工作分支创建另一个分支。
  2. git pull / git合并包含要复制的文件的修订版(SHA1)。因此,这将合并您的所有更改,但是我们仅使用此分支来抓取一个文件。
  3. 修复所有冲突等。调查您的文件。
  4. 结帐您的工作分支
  5. 检出从合并提交的文件。
  6. 提交。

我尝试打补丁,但情况太丑陋了。简而言之,它看起来像这样:

工作分支:A实验分支:B(包含file.txt,其中包含我要折叠的更改。)

git checkout A

创建基于A的新分支:

git checkout -b tempAB

将B合并到tempAB中

git merge B

复制合并的sha1哈希:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <matthewe@matthewe.com>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

签出您的工作分支:

git checkout A

检出您的固定文件:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

在那儿,你应该拥有它。提交结果。


3
因此,我们必须做所有这一切只是为了合并一个文件?岂不是更容易复制和粘贴文件到另一个分支
罗宾

1
@Robin可能不会,因为合并会保留文件的更改,分支A和分支B之间的差异会有所不同。复制文件将覆盖工作分支A和您想从B引入的分支之间的任何其他差异,其中可能不包含这些差异这些条目/编辑。例如,犯罪嫌疑人AB其他方面开始改头换面。复制将消除这些差异。
blamb

13

这使用git的内部difftool。可能需要做一些工作,但要直截了当。

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.

1
为了阐明--(空参数标签)的使用,git checkout docs:ARGUMENT DISAMBIGUATION说:“ git checkout -- <pathspec>如果要从索引中检出这些路径,则使用。” 这是因为您可能具有相同名称的分支和文件/路径。在这种情况下,git会选择在默认情况下签出该分支,而不是让您消除歧义该分支或该路径是否应该被签出的歧义。但是,如果--先行者git将会检出文件/路径。
SherylHohman

8

我发现这种方法简单实用:如何“合并”另一个分支中的特定文件

事实证明,我们正在努力。我们的好朋友git checkout是完成这项工作的正确工具。

git checkout source_branch <paths>...

我们可以简单地给git checkout提供功能分支A的名称,以及要添加到主分支的特定文件的路径。

请阅读全文以获得更多理解


2
这将覆盖文件,它不会将它们合并
亚历克斯·G

对于您而言,这取决于您在做什么以及您想要达到的目标。这里的想法是分支B是A的分支,您在B中修改了4个文件,但只想将B中的2个文件合并到A中。常规合并将合并所有4个文件,您可以在此处选择。由于B实质上包含较新的文件,因此它们看起来像被覆盖了。您需要一些证据来支持您的经验。
Pawel Cioch

我同意它会覆盖。我认为您的意思是-p在该命令中使用该选项。不幸的是,在补丁更改之前,它会覆盖工作树文件上先前从签出分支转移的任何部分。
blamb

好主意是从2009年开始的,新版本的git的行为可能有所不同,并且需要-p或其他任何内容,但是回到我发布它的时候,它对我有用,但是也许我也不在乎文件被覆盖了,因为我需要的是最新版本
Pawel Cioch


3

以下命令将(1)比较正确分支的文件,以掌握(2)交互地询问您要应用哪些修改。

git checkout-补丁大师


0

我的编辑被拒绝了,所以我在这里附加了如何处理来自远程分支的合并更改。

如果必须在错误合并之后执行此操作,则可以执行以下操作:

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.

0

假设B是当前分支:

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

请注意,这仅将更改应用于本地文件。之后,您需要提交。


对我来说,这会产生一个error: <file-path>: already exists in working directory
kontur,2017年

您应该在当前目录中指定文件或文件路径。我正在使用git diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri,

0

您可以签出要合并的文件的旧版本,将其保存为其他名称,然后运行两个文件上的合并工具。

例如。

git show B:src/common/store.ts > /tmp/store.ts (其中B是分支名称/提交/标签)

meld src/common/store.ts /tmp/store.ts


0

我会这样做

git format-patch branch_old..branch_new file

这将为该文件生成一个补丁。

在目标branch_old上应用补丁

git am blahblah.patch


您可以轻松地查看补丁以提高安全性吗?
XavierStuvw,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.