git 如何在git中合并子目录?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1214906/
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 06:49:03  来源:igfitidea点击:

How do I merge a sub directory in git?

git

提问by Brad Gessler

Is it possible to merge only the changes for a sub-directory from a local git branch to a remote git branch or is it "all or nothing"?

是否可以仅将子目录的更改从本地 git 分支合并到远程 git 分支,还是“全有或全无”?

For example, I have:

例如,我有:

branch-a
 - content-1
 - dir-1
   - content-2

and

branch-b
 - content-1
 - dir-1
   - `content-2

I only want to merge the contents of branch-a dir-1 with the contents of branch-b dir-1.

我只想将 branch-a dir-1 的内容与 branch-b dir-1 的内容合并。

回答by VonC

Just as an alternative to the SO question "How do you merge selective files with git-merge?", I just found this GitHub threadwhich could be more adapted for merging a whole subdirectory, based on git read-tree:

作为 SO 问题“如何将选择性文件与 git-merge 合并?”的替代方案,我刚刚发现了这个 GitHub 线程,它更适合基于git read-tree合并整个子目录:

  • My repository => cookbooks
    My repository target directory => cookbooks/cassandra

  • Remote repository => infochimps
    Remote repository source I want merged into cookbooks/cassandra=> infochimps/cookbooks/cassandra

Here are the commands I used to merge them

  • Add the repository and fetch it
  • 我的存储库 =>cookbooks
    我的存储库目标目录 =>cookbooks/cassandra

  • 远程存储库 =>infochimps
    我要合并到的远程存储库源cookbooks/cassandra=>infochimps/cookbooks/cassandra

这是我用来合并它们的命令

  • 添加存储库并获取它
git remote add -f infochimps git://github.com/infochimps/cluster_chef.git
  • Perform the merge
  • 执行合并
git merge -s ours --no-commit infochimps/master
  • Merge only infochimps/cookbooks/cassandrainto cassandra
  • 只合并infochimps/cookbooks/cassandracassandra
git read-tree --prefix=cassandra/ -u infochimps/master:cookbooks/cassandra
  • Commit the change
  • 提交更改
 git commit -m 'merging in infochimps cassandra'


Addendum

附录

It's bizarre,[edit me]— but the read-treestep can possibly fail like this:

这很奇怪,[编辑我]- 但是这read-tree一步可能会像这样失败:

error: Entry 'infochimps/cookbooks/cassandra/README' overlaps with 'cookbooks/cassandra/README'. Cannot bind.

error: Entry 'infochimps/cookbooks/cassandra/README' overlaps with 'cookbooks/cassandra/README'. Cannot bind.

... even when both files are identical. This might help:

...即使两个文件相同。这可能有帮助:

git rm -r cassandra
git read-tree --prefix=cassandra/ -u infochimps/master:cookbooks/cassandra

But off course, verify manually that this does what you want.

但是当然,手动验证这是否符合您的要求。

回答by Chris Arena

For my example, assume you have a branch 'source' and a branch 'destination' which both reflect upstream versions of themselves (or not, if local only) and are pulled to the latest code. Let's say I want the subdirectory in the repo called newFeature which only exists in the 'source' branch.

对于我的示例,假设您有一个分支 'source' 和一个分支 'destination',它们都反映了它们自己的上游版本(或者不是,如果只是本地版本)并被拉到最新的代码。假设我想要 repo 中名为 newFeature 的子目录,它只存在于“源”分支中。

git checkout destination
git checkout source newFeature/
git commit -am "Merged the new feature from source to destination branch."
git pull --rebase
git push

Significantly less convoluted than everything else I've seen and this worked perfectly for me, found here.

明显比我见过的其他所有东西都少复杂,这对我来说非常有用,在这里找到

Note that this isn't a 'real merge' so you won't have the commit information about newFeature in the destination branch, just the modifications to the files in that subdirectory. But since you're presumably going to merge the entire branch back over later, or discard it, that might not be an issue.

请注意,这不是“真正的合并”,因此您不会在目标分支中拥有有关 newFeature 的提交信息,只有对该子目录中文件的修改。但是由于您可能会稍后合并整个分支,或者丢弃它,所以这可能不是问题。

回答by tobiasbayer

I got this from a forum threadat Eclipse and it worked like a charm:

我从Eclipse 的一个论坛帖子中得到了这个,它的作用就像一个魅力:

git checkout source-branch
git checkout target-branch <directories-or-files-you-do-**NOT**-want> 
git commit
git checkout target-branch
git merge source-branch

回答by xno

Given OP's scenario where they have two branches but want to merge only the history of dir-1from branch-ainto branch-b:

鉴于 OP 的场景,他们有两个分支,但只想将dir-1的历史从branch-a合并到branch-b

# Make sure you are in the branch with the changes you want
git checkout branch-a

# Split the desired folder into its own temporary branch
# This replays all commits, so it could take a while
git subtree split -P dir-1 -b temp-branch

# Enter the branch where you want to merge the desired changes into
git checkout branch-b

# Merge the changes from the temporary branch
git subtree merge -P dir-1 temp-branch

# Handle any conflicts
git mergetool

# Commit
git commit -am "Merged dir-1 changes from branch-a"

# Delete temp-branch
git branch -d temp-branch

回答by Robert

Use git cherry-pickto select the commits you want and merge only these commits. The key trick here is to get these commits in an easy way(so that you don't have to figure out them by manually checking the git log and entering them by hand). Here's how: use git logto print the commit's sha1 id, like this:

使用git cherry-pick来选择您想要的提交和合并只有这些提交。这里的关键技巧是以简单的方式获取这些提交(这样您就不必通过手动检查 git 日志并手动输入来找出它们)。方法如下:用于git log打印提交的 sha1 id,如下所示:

git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>

git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>

commit-a is the commit immediately before the start point of the branch to merge, commit-b is the last commit on the branch to merge. --reverse prints these commit in reverse order for cherry pick later.

commit-a 是要合并的分支起点之前的提交,commit-b 是要合并的分支上的最后一次提交。--reverse 以相反的顺序打印这些提交,以便稍后挑选。

Then do it like:

然后这样做:

git cherry-pick $(git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>)

git cherry-pick $(git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir>)

Two steps, simple and stable!

两步,简单稳定!

回答by Sun Yin

create git repo contains both branch-a and branch-b

创建 git repo 包含分支 a 和分支 b

git checkout branch-a
git diff branch-b dir-1 > a.diff
patch -R -p1 < a.diff