如何在Git中合并特定文件

13

假设我有一个在MASTER分支上的项目,其中有数百个PHP文件。为了进行项目中的漏洞修复,我创建了一个单独的分支。

git checkout -b bugfix

然后,在修复了3个文件中的错误之后(例如index.php,register.php和login.php),我将其合并到主分支中。

git checkout master
git merge bugfix

上述代码将合并我所做更改的所有3个文件,但是否有任何方式可以强制GIT仅合并2个文件,比如只有login.php和register.php?


1
我认为一种方法是将这两个文件提交到一个提交中,将最后一个文件提交到另一个提交中,你可以指定一个提交并合并它。 - dutt
@dutt,OP的问题是文件更改已经提交了,我假设。 - arkascha
也许这可以帮助找到方法 https://dev59.com/9nRB5IYBdhLWcg3w-789 - hellectronic
你确定你真的想要一个 Git 没有针对优化的工作流吗?对我来说,如果你打算分别合并它们,那么你应该改变你的工作流,并创建两个 bugfix 分支。 - Micha Wiedenmann
4个回答

15

有两种方法:


方法一

以下解决方案摘自博客文章

事实证明,checkout 命令在这个问题上也很有用。你可以从另一个分支中直接调出(checkout)那些特定的文件:

# switch to the branch you want to be your merge destination
git checkout master

# checkout specific files from specific branch (e.g bugfix)
# format: git checkout <source branch> <file.1> <file.2> ... <file.N>
git checkout bugfix login.php register.php

# check the status
git status

# merge them in
git commit -m "your merge comment"

第二种方法

这是一种简单的备选方法,但只适用于每个文件有一个提交记录的情况(也就是每次更改文件后,您都会进行一次提交,然后再移动到下一个文件)。在这种情况下,您可以将这些特定的提交记录带到另一个分支(在您的情况下是主分支):

# get which commit you want to take to the other branch (first 7 characters will do)
git log

# switch to the branch you want to be your merge destination
git checkout master

# bring specific commit to this branch (replace the 63344f2 with your own 7 character commit ID)
git cherry-pick 63344f2

它没有将分支合并到“master”中。 - axiac
3
如果您仔细地阅读问题,您会意识到问题不是关于合并分支,而是关于合并文件(这是将另一个分支中的特定文件带到所需分支的错误术语)。上面的解决方案有效。 - Mehrad Mahmoudian

1
你可以模拟你想要的行为,但是你在第三个文件上所做的更改会发生什么?
第三个文件的更改将保留在分支的提交中,但它们不会出现在合并的提交中,就像文件在分支上根本没有被修改一样。
这是你可以做的方式:
git checkout master
git merge bugfix --no-commit

--no-commit选项告诉git在合并文件后停止提交。现在,您可以检查文件,更改文件,并进行任何操作。如果要取消对index.php所做的更改,可以运行以下命令:

git checkout master -- index.php

运行git status,您会发现index.php不再出现为修改状态(无论是在索引中还是工作树中)。现在,您可以git commit并完成操作。

这个解决方案就像是改变所有文件,然后尝试手动纠正混乱!阅读此帖子以了解此堆栈的内容以及为什么您的解决方案是浪费时间和劳动力。 - Mehrad Mahmoudian

1
Git中无法记录部分合并,所有合并必须合并所有被合并提交的根树。当然,您可以选择通过从父级之一选择未更改的文件副本来解决该合并,但这仍然是一个“完整”的合并,并且在涉及的分支之间进行后续变基或合并时,该文件中的更改将被视为已合并。

0

不,没有直接的方法。但是,您可以从要合并的分支中选择文件,并将它们覆盖到主分支中现有的文件上。命令顺序应为:

git checkout master
git show bugfix:login.php > login.php
git show bugfix:register.php > register.php
git add .
git commit -m "Select login and register from branch/bugfix"

好的,上面的方法将“破坏”文件历史记录。在这个邮件列表中有一个关于相同问题的旧讨论。

从技术角度来看,使历史记录成为重要事情的是它给我们提供了一个共同的祖先,以及“按日期排序的一组提交”的无用性。而且才是唯一重要的。

现在,对于做每个文件的历史记录有什么根本性的错误呢?

如果你已经跟上了这个论点,你会说:“啊哈!显然!”。

忽略很多段落之后,你会找到解决方法:

git diff commit..othercommit filename | git-apply --index && git commit

在您的情况下,commit = 您的 HEAD/master 分支的哈希值;而 othercommit = bugfix 分支的哈希值。

它不会将分支合并到master - axiac

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