如何在Git中有选择地合并或选择来自另一个分支的更改?

Dav*_*ner 1374 git git-merge git-patch git-cherry-pick

我在一个新项目上使用git,该项目有两个并行 - 但目前是实验性的 - 开发分支:

  • master:导入现有的代码库加上一些我一般都知道的mod
  • exp1:实验分支#1
  • exp2:实验分支#2

exp1exp2代表两种截然不同的架构方法.直到我走得更远,我无法知道哪一个(如果有的话)会起作用.当我在一个分支中取得进展时,我有时会在另一个分支中进行编辑,并且只想合并那些.

将选择性更改从一个开发分支合并到另一个开发分支而将其他所有内容合并的最佳方法是什么?

我考虑过的方法:

  1. git merge --no-commit 然后手动取消大量编辑,我不想在分支之间做出共同点.

  2. 手动将公共文件复制到临时目录,然后git checkout移动到另一个分支,然后更多地手动从临时目录复制到工作树中.

  3. 以上的变化.暂时放弃exp分支并使用另外两个本地存储库进行实验.这使得手动复制文件更加简单.

所有这三种方法都显得乏味且容易出错.我希望有更好的方法; 类似于过滤器路径参数的东西会git-merge更具选择性.

Sus*_*adi 940

我有与上面提到的完全相同的问题.但我在解释答案时发现这一点更清楚了.

摘要:

  • 这不是真正的合并.您按文件而不是按提交选择更改,您将丢失任何现有的提交信息(作者,消息).当然,如果你想合并一些文件中的所有更改,这很好,你必须重新做所有提交.但是,如果文件包含要合并的更改和其他要丢弃的更改,则其他答案中提供的方法之一将更好地为您服务. (248认同)
  • 看看你也可以使用的变化:`git diff --cached` (12认同)
  • @mykhal和其他人:这会自动对索引中的文件进行分阶段,所以如果你检查了`foo.c`,请执行`git reset HEAD foo.c`来取消暂存该文件,然后你可以对其进行区分.我在尝试之后发现了这一点并回到这里寻找答案 (10认同)
  • Bart J的链接文章是最好的方法.清晰,简单,一个命令.这是我即将使用的那个.:) (9认同)
  • 根据这个[回答](http://stackoverflow.com/a/13712429/2458234)`git checkout -p <revision> - <path>`将与你描述的前三个命令相同:) (8认同)
  • @spacemanaki有我认为最好的答案.`git checkout feature-branch foo.c`后跟`git reset HEAD foo.c`然后是`git add -p`来引入你想要的差异或排除坏的,然后`git commit foo.c`来保存您的更改,并使用`git checkout foo.c`重置索引.工作就像一个魅力. (2认同)
  • 接受@Zach 的建议对我有用。要对其进行扩展,如果您使用 difftool,则可以使用 `git difftool origindevelop src/main/path/to/file.ext` 并引入您需要的代码行。如果您只想抓取几行,此方法特别有效。 (2认同)
  • 我是唯一一个在这里看不到答案的人吗?我所看到的只是“我遇到了与您上面提到的完全相同的问题。但我发现在解释答案时更清楚了。” (2认同)
  • @Pistos,我在这个页面上找不到'Bart J'.也许自2009年10月以来用户名/等已经发生了变化? (2认同)
  • 这不是真正的合并,但它正是我想要的! (2认同)
  • 这是**不**合并,它是替代。更接近按文件进行实际合并的操作可能是`git diff branch1 branch2 filepath &gt; 1.patch` 然后是`git apply 1.patch`。当然,它只会带来纯粹的文件更改,而没有其他任何内容。 (2认同)

180*_*ION 454

您可以使用cherry-pick命令从一个分支获取单个提交.

如果您想要的更改不在单独的提交中,那么使用此处显示的方法将提交拆分为单独的提交.粗略地说,您使用git rebase -i原始提交进行编辑,然后git reset HEAD^有选择地还原更改,然后git commit将该位提交为历史记录中的新提交.

在Red Hat Magazine中还有另一个不错的方法,如果你想将不同的更改分成单个文件(在该页面中搜索"split"),他们使用git add --patch或者可能git add --interactive允许你只添加一部分块.

拆分更改后,您现在可以选择您想要的更改.

  • 从技术上讲,这是正确的答案,正确的答案确实显得"错综复杂".---更高的投票答案只是一个快速而肮脏的"诀窍"答案,对大多数人来说就是他们所关注的(: (51认同)
  • 根据我的理解,这比投票得多的答案更令人费解. (13认同)
  • 我只是想分享另一种方法,这种方法看起来最干净,最不那么令人费解:http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-另一个分支/完全简单和令人敬畏 (13认同)
  • 关于哪种方法"正确"的辩论感到困惑?考虑[文件和提交之间的差异(参见底部的备注)](http://stackoverflow.com/documentation/git/244/staging#t=20160826045846751695).OP希望合并FILES并且不提及COMMITS.投票率较高的答案特定于文件; 接受的答案使用cherry-pick,这是特定于提交.Cherry-pick可能是有选择地合并提交的关键,但将文件从一个分支移动到另一个分支可能会非常痛苦.虽然提交是git强项的核心,但不要忘记文件仍有作用! (11认同)
  • @akaihola:HEAD ^是正确的.请参阅man git-rev-parse:修订参数的后缀^表示该提交对象的第一个父级.前缀^表示法用于排除从提交可到达的提交. (3认同)

alv*_*bad 315

要有选择地将文件从一个分支合并到另一个分支,请运行

git merge --no-ff --no-commit branchX
Run Code Online (Sandbox Code Playgroud)

branchX您想要合并到当前分支的分支在哪里.

--no-commit选项将暂存已由Git合并而不实际提交它们的文件.这将使您有机会根据需要修改合并的文件,然后自己提交.

根据您要合并文件的方式,有四种情况:

1)你想要一个真正的合并.

在这种情况下,您接受合并文件的方式是Git自动合并它们然后提交它们.

2)有些文件你不想合并.

例如,您希望保留当前分支中的版本并忽略要合并的分支中的版本.

要选择当前分支中的版本,请运行:

git checkout HEAD file1
Run Code Online (Sandbox Code Playgroud)

这将检索file1当前分支的版本并覆盖file1Git 的automerged.

3)如果你想在branchX中使用该版本(而不是真正的合并).

跑:

git checkout branchX file1
Run Code Online (Sandbox Code Playgroud)

这将检索由Git自动合并的file1in branchX和overrite 的版本file1.

4)最后一种情况是,如果您只想选择特定的合并file1.

在这种情况下,您可以file1直接编辑修改后的内容,将其更新为您想要的版本file1,然后提交.

如果Git无法自动合并文件,它会将文件报告为"未合并 "并生成一个副本,您需要手动解决冲突.



为了进一步解释一个例子,假设你要合并branchX到当前分支:

git merge --no-ff --no-commit branchX
Run Code Online (Sandbox Code Playgroud)

然后,运行该git status命令以查看已修改文件的状态.

例如:

git status

# On branch master
# Changes to be committed:
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      file4
#
Run Code Online (Sandbox Code Playgroud)

哪里file1,file2file3,git文件已经成功自动合并.

这意味着,在变化masterbranchX所有这三个文件已经被结合在一起,没有任何冲突.

您可以通过运行git diff --cached; 来检查合并的完成方式.

git diff --cached file1
git diff --cached file2
git diff --cached file3
Run Code Online (Sandbox Code Playgroud)

如果您发现某些合并不受欢迎,那么您可以

  1. 直接编辑文件
  2. 保存
  3. git commit

如果您不想合并file1并希望在当前分支中保留该版本

git checkout HEAD file1
Run Code Online (Sandbox Code Playgroud)

如果您不想合并file2,只想要版本branchX

git checkout branchX file2
Run Code Online (Sandbox Code Playgroud)

如果您想file3自动合并,请不要做任何事情.

Git已经在这一点上合并了它.


file4上面是Git失败的合并.这意味着在同一行上发生的两个分支都发生了变化.您需要手动解决冲突.您可以通过直接编辑文件或对要file4成为分支的版本运行checkout命令来放弃已完成的合并.


最后,别忘了git commit.

  • 与得票最多的答案不同,这个解决方案保留了我的合并历史记录,这对我很重要,因为我在分支机构之间来回编织部分提交.我没有尝试所有其他建议的解决方案,所以也许他们中的一些也这样做. (19认同)
  • @cfi如何添加`--no-ff`以防止这种行为? (15认同)
  • 但要小心:如果`git merge --no-commit branchX`只是一个快进,指针将被更新,因此--no-commit被忽略 (10认同)
  • 该解决方案可提供最佳结果和灵活性. (7认同)
  • 我绝对建议用Eduardo的"--no-ff"选项更新这个答案.我仔细阅读了整个事情(其他方面很棒)只是为了让我的合并得到快速转发. (5认同)
  • 小心.此合并在一个方向上工作,但如果您决定将上游主服务器合并回源分支,则合并中未包含的文件将被视为DELETED.我使用git-flow类进程使用主分支(生产主线),登台分支(登台服务器主线)和基于登台分支的主题分支.使用这种策略导致我从主服务器"反向合并"回到暂存状态,从而完全失败,认为我没有从阶段到主服务器合并的所有内容都被删除.这包括整个文件和帅哥.你被警告了 (5认同)
  • 如果您发现“currentBranch”中不存在“file1”并且您不想将其作为合并的一部分提交,请在提交之前手动将其删除。尝试执行 `git checkout HEAD file1` 将失败。 (2认同)
  • 扩展@PabloAdames 的评论:请注意,`file1` 已经被暂存,所以要从暂存中删除文件,我会在`git reset file1` *before* 手动删除它之前,或者`git add file1` *after*手动删除。 (2认同)

nos*_*ian 102

我不喜欢上述方法.使用cherry-pick非常适合选择单个更改,但如果您想引入除了一些不良更改之外的所有更改,那将是一种痛苦.这是我的方法.

没有--interactive参数可以传递给git merge.

这是替代方案:

你在分支'特征'中有一些变化,你想要以一种不邋way的方式将一些但不是全部的变为'master'(即你不想挑选并提交每一个)

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp
Run Code Online (Sandbox Code Playgroud)

所以只需将它包装在一个shell脚本中,将master更改为$ to并将功能更改为$ from,您就可以了:

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp
Run Code Online (Sandbox Code Playgroud)

  • 您可能希望将`git rebase -i $ to`更改为`git rebase -i $ to || $ SHELL`,这样如果rebase失败,用户可以根据需要调用`git --skip`等.还值得用"&&"而不是换行链接这些行. (4认同)
  • 不幸的是,似乎答案中的链接已经死了. (2认同)

Chr*_*ial 89

还有另外一种方法:

git checkout -p
Run Code Online (Sandbox Code Playgroud)

这是之间的混合git checkout,并git add -p与可能相当地正是你正在寻找:

   -p, --patch
       Interactively select hunks in the difference between the <tree-ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree-ish> was specified, the index).

       This means that you can use git checkout -p to selectively discard
       edits from your current working tree. See the “Interactive Mode”
       section of git-add(1) to learn how to operate the --patch mode.
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最简单,最简单的方法,只要您只有可管理的更改数量即可合并.我希望更多的人会注意到这个答案并提出它.示例:git checkout --patch exp1 file_to_merge (9认同)
  • 关于这个问题的类似答案:http://stackoverflow.com/a/11593308/47185 (2认同)
  • 真正最简单的方法。git checkout -p featurebranch文件名。最好的是,当命令运行时,它会给您ay / n / e /?/ ...等。决定如何合并文件的选项。我尝试使用e,甚至可以在应用之前编辑补丁。多么酷。真正的一个班轮,用于合并其他分支机构的选择性文件。 (2认同)

Eri*_* Hu 52

虽然其中一些答案非常好,但我觉得没有人真正回答OP的原始约束:从特定分支中选择特定文件.这个解决方案可以做到这一点,但如果有很多文件可能会很乏味.

比方说你有master,exp1exp2分支机构.您希望将每个实验分支中的一个文件合并为主文件.我会做这样的事情:

git checkout master
git checkout exp1 path/to/file_a
git checkout exp2 path/to/file_b

# save these files as a stash
git stash
# merge stash with master
git merge stash
Run Code Online (Sandbox Code Playgroud)

这将为您提供所需的每个文件的文件内差异.而已.没什么.在版本之间进行完全不同的文件更改很有用 - 在我的例子中,将应用程序从Rails 2更改为Rails 3.

编辑:这将合并文件,但进行智能合并.我无法弄清楚如何使用这种方法来获取文件内差异信息(可能它仍然会出现极端差异.除非你使用该-s recursive -X ignore-all-space选项,否则像空白一样的烦人的小东西会被合并回来)

  • 另请注意:您可以从所有内联的分支执行多个文件,例如`git checkout exp1 path/to/file_a path/to/file_x` (4认同)
  • 这很漂亮.我做了`git checkout feature <path>/*`来获取文件组. (2认同)
  • 哦,我觉得这很清楚.这样它就可以合并一个文件,而不必覆盖目标分支上的先前更改. (2认同)

Cor*_*ory 47

1800 INFORMATION的答案完全正确.然而,作为一个git noob,"使用git cherry-pick"还不足以让我在互联网上更多地挖掘这一点,所以我想我会发布一个更详细的指南以防其他人在类似的船.

我的用例是想要有选择地将其他人的github分支中的更改转换为我自己的.如果您已经有一个包含更改的本地分支,则只需执行步骤2和5-7.

  1. 创建(如果未创建)包含您要引入的更改的本地分支.

    $ git branch mybranch <base branch>

  2. 切换到它.

    $ git checkout mybranch

  3. 从其他人的帐户中下拉您想要的更改.如果您还没有将它们添加为遥控器.

    $ git remote add repos-w-changes <git url>

  4. 从他们的分支拉下一切.

    $ git pull repos-w-changes branch-i-want

  5. 查看提交日志以查看所需的更改:

    $ git log

  6. 切换回要将更改拉入的分支.

    $ git checkout originalbranch

  7. 樱桃用哈希一个接一个地挑选你的提交.

    $ git cherry-pick -x hash-of-commit

帽子提示:http://www.sourcemage.org/Git_Guide

  • 提示:首先使用`git cherry`命令(请参见手册)来识别尚未合并的提交. (3认同)

mae*_*tr0 42

以下是如何使用in branch 替换分支中的Myclass.java文件.它即使不存在也会起作用.masterMyclass.javafeature1Myclass.javamaster

git checkout master
git checkout feature1 Myclass.java
Run Code Online (Sandbox Code Playgroud)

请注意,这将覆盖 - 而不是合并 - 而忽略主分支中的本地更改.

  • 这不会合并.它只会使用feature1分支的更改覆盖master上的更改. (6认同)
  • 完美的是,我正在寻找这种合并,其中`theirs`覆盖`ours` => +1干杯;) (3认同)

mas*_*omi 28

实际合并来自两个分支的特定文件的简单方法,不仅仅是将特定文件替换为另一个分支中的文件.

第一步:扩散分支

git diff branch_b > my_patch_file.patch

创建当前分支和branch_b之间差异的补丁文件

第二步:在匹配模式的文件上应用补丁

git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch

关于选项的有用说明

您可以*在包含模式中用作通配符.

斜杠不需要转义.

此外,您可以使用--exclude并将其应用于除匹配模式的文件之外的所有内容,或者使用-R反转补丁

-p1选项是来自*unix patch命令的保留,以及补丁文件的内容在每个文件名前面加上a/或者b/(或者更多取决于补丁文件的生成方式)你需要删除它以便它可以弄清楚这一事实真实文件到补丁需要应用的文件路径.

查看git-apply的手册页以获取更多选项.

第三步:没有第三步

显然你想要提交你的更改,但是谁说你在提交之前没有其他相关的调整.

  • 这在 current_branch 有许多需要保留的“附加”更改时非常有用。得到了仅由 branch_b 带来的变化的差异: git diff HEAD...branch_b (是的 - 三个时期是魔术)。 (2认同)

jej*_*ese 23

以下是如何让历史记录只关注来自另一个分支的几个文件,即使更简单的"合并"会带来更多您不想要的更改.

首先,您将采取不同寻常的步骤,提前声明您要提交的内容是合并,而不是git对工作目录中的文件执行任何操作:

git merge --no-ff --no-commit -s ours branchname1
Run Code Online (Sandbox Code Playgroud)

...其中"branchname"是你声称要合并的东西.如果你马上提交,它将不做任何改变,但它仍会显示来自另一个分支的祖先.您可以添加更多分支/标签/等.如果需要,也可以到命令行.但是,此时提交没有更改,因此请从其他修订中获取文件.

git checkout branchname1 -- file1 file2 etc
Run Code Online (Sandbox Code Playgroud)

如果您要从多个其他分支合并,请根据需要重复.

git checkout branchname2 -- file3 file4 etc
Run Code Online (Sandbox Code Playgroud)

现在,来自其他分支的文件位于索引中,准备提交,具有历史记录.

git commit
Run Code Online (Sandbox Code Playgroud)

你会在提交消息中做很多解释.

但请注意,如果不清楚,这是搞乱的事情要做.它不符合"分支"的精神,而樱桃选择是一种更诚实的方式来做你在做的事情.如果你想为你上次没有带来的同一个分支上的其他文件做另一个"合并",那么它将以"已经是最新的"消息阻止你.这是我们应该拥有的不分支的症状,在"from"分支中应该是不止一个不同的分支.

  • 你的第一个命令(`git merge --no-ff --no-commit -s outs branchname1`)正是我想要的!谢谢! (3认同)

Fel*_*lix 15

我知道我有点晚了,但这是我合并选择性文件的工作流程.

#make a new branch ( this will be temporary)
git checkout -b newbranch
# grab the changes 
git merge --no-commit  featurebranch
# unstage those changes
git reset HEAD
(you can now see the files from the merge are unstaged)
# now you can chose which files are to be merged.
git add -p
# remember to "git add" any new files you wish to keep
git commit
Run Code Online (Sandbox Code Playgroud)


Stu*_*ner 15

我发现这篇文章包含了最简单的答案.仅仅做:

$ #git checkout <branch from which you want files> <file paths>
Run Code Online (Sandbox Code Playgroud)

例:

$ #pulling .gitignore file from branchB into current branch
$ git checkout branchB .gitignore
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅帖子.

  • 这并没有真正合并,它会覆盖当前分支上的文件. (3认同)
  • @igrali 这是一个有用的评论,但与“正确”方法的难度相比,这是一个很好的解决方法。人们必须非常小心。 (2认同)

dsi*_*zko 14

最简单的方法是将您的仓库设置为要合并的分支然后运行,

git checkout [branch with file] [path to file you would like to merge]
Run Code Online (Sandbox Code Playgroud)

如果你跑

git status
Run Code Online (Sandbox Code Playgroud)

你会看到文件已经上演了......

然后跑

git commit -m "Merge changes on '[branch]' to [file]"
Run Code Online (Sandbox Code Playgroud)

简单.

  • 这将完全替换源分支中的文件内容而不是合并 (4认同)
  • 这是我发现的几乎最好的答案.请参阅http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/如此清晰,简洁,它只是有效! (3认同)
  • 我正要这样回答,我以为我发明了尚未回答的新事物!但这是**最简单的方法**。这个应该在最上面! (2认同)

小智 12

奇怪的是,git仍然没有"开箱即用"的便利工具.我只是通过当前版本分支的一些错误修正来更新一些旧版本分支(它仍然有很多软件用户)时大量使用它.在这种情况下,经常需要从trunk中的文件中快速获取一些代码行,忽略了许多其他更改(不应该进入旧版本)...当然还有交互式三向合并在这种情况下需要,git checkout --patch <branch> <file path>不适用于这种选择性合并目的.

你可以轻松地做到:

只需将此行添加到[alias]全局.gitconfig或本地.git/config文件中的部分:

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; /C/BCompare3/BCompare.exe $2.theirs $2 $2.base $2; rm -f $2.theirs; rm -f $2.base;' -"
Run Code Online (Sandbox Code Playgroud)

它意味着你使用Beyond Compare.如果需要,只需更改为您选择的软件.或者,如果您不需要交互式选择性合并,则可以将其更改为三向自动合并:

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; git merge-file $2 $2.base $2.theirs; rm -f $2.theirs; rm -f $2.base;' -"
Run Code Online (Sandbox Code Playgroud)

然后像这样使用:

git mergetool-file <source branch> <file path>
Run Code Online (Sandbox Code Playgroud)

这将为您提供其他分支中任何文件的真正选择性树形合并机会.


Fel*_*ipe 9

这不完全是你想要的,但它对我有用:

git checkout -p <branch> -- <paths> ...
Run Code Online (Sandbox Code Playgroud)

这是一些答案的混合.

  • 这确实很有用,可以添加到对我来说最好的答案中,@alvinabad 的答案。执行时:`git checkout HEAD file1` 保留当前版本并取消合并文件`file1`,可以使用`-p` 选项选择要合并的文件的*部分*。谢谢你的窍门! (3认同)

Sus*_*adi 8

我有与上面提到的完全相同的问题.但我发现这个git博客更清楚地解释了答案.

来自以上链接的命令:

#You are in the branch you want to merge to
git checkout <branch_you_want_to_merge_from> <file_paths...>
Run Code Online (Sandbox Code Playgroud)

  • 你测试过这个吗?我确信这些文件将从 &lt;branch_you_want_to_merge_from&gt; 替换而不是被合并 (2认同)

lum*_*idu 7

我会做的

git diff commit1..commit2 filepattern | git-apply --index && git commit

这样,您可以限制来自分支的文件模式的提交范围.

被盗:http://www.gelato.unsw.edu.au/archives/git/0701/37964.html

  • 巴特 Js 是谁? (2认同)

Wad*_*ade 7

我喜欢上面的'git-interactive-merge'答案,但有一个更简单.让git使用交互式的rebase组合为你做这个:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o master
Run Code Online (Sandbox Code Playgroud)

所以情况是你想要来自'feature'分支的C1和C2(分支点'A'),但现在不需要其余的.

# git branch temp feature
# git checkout master
# git rebase -i --onto HEAD A temp
Run Code Online (Sandbox Code Playgroud)

如上所述,您将进入交互式编辑器,在该编辑器中为C1和C2选择"拾取"行(如上所述).保存并退出,然后它将继续使用rebase并给你分支'temp'和HEAD在master + C1 + C2:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o-master--C1---C2 [HEAD, temp]
Run Code Online (Sandbox Code Playgroud)

然后你可以将master更新为HEAD并删除temp分支,你很高兴:

# git branch -f master HEAD
# git branch -d temp
Run Code Online (Sandbox Code Playgroud)


Gar*_*One 7

git reset --soft branch呢 我很惊讶没有人提及它。

对我来说,这是从另一分支中选择性地选择更改的最简单方法,因为此命令将所有diff更改放入我的工作树中,因此我可以轻松地选择或还原所需的内容。这样,我可以完全控制提交的文件。


And*_*ndy 6

我知道这个问题很老,还有很多其他答案,但是我编写了自己的脚本'pmerge'来部分合并目录.这是一项正在进行的工作,我仍在学习git和bash脚本.

此命令使用git merge --no-commit然后取消应用与提供的路径不匹配的更改.

用法:git pmerge branch path
示例:git merge develop src/

我没有广泛测试过它.工作目录应该没有任何未提交的更改和未跟踪的文件.

#!/bin/bash

E_BADARGS=65

if [ $# -ne 2 ]
then
    echo "Usage: `basename $0` branch path"
    exit $E_BADARGS
fi

git merge $1 --no-commit
IFS=$'\n'
# list of changes due to merge | replace nulls w newlines | strip lines to just filenames | ensure lines are unique
for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do
    [[ $f == $2* ]] && continue
    if git reset $f >/dev/null 2>&1; then
        # reset failed... file was previously unversioned
        echo Deleting $f
        rm $f
    else
        echo Reverting $f
        git checkout -- $f >/dev/null 2>&1
    fi
done
unset IFS
Run Code Online (Sandbox Code Playgroud)


ken*_*orb 5

您可以使用read-tree将给定的远程树读取或合并到当前索引中,例如:

git remote add foo git@example.com/foo.git
git fetch foo
git read-tree --prefix=my-folder/ -u foo/master:trunk/their-folder
Run Code Online (Sandbox Code Playgroud)

要执行合并,请-m改用。

另请参阅:如何在 Git 中合并子目录?


Dav*_*e C 5

按文件选择性合并/提交的简单方法:

git checkout dstBranch
git merge srcBranch

// Make changes, including resolving conflicts to single files
git add singleFile1 singleFile2
git commit -m "message specific to a few files"
git reset --hard # Blow away uncommitted changes
Run Code Online (Sandbox Code Playgroud)