如何在git中合并子目录?

时间:2009-07-31 21:07:33

标签: git

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

例如,我有:

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

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

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

7 个答案:

答案 0 :(得分:73)

作为SO问题“How do you merge selective files with git-merge?”的替代方案,我刚刚找到this GitHub thread,它可以更适合合并整个子目录,基于 git read-tree

  
      
  • 我的存储库=> cookbooks
      我的存储库目标目录=> cookbooks/cassandra

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

  •   
     

以下是我用来合并它们的命令

     
      
  • 添加存储库并获取
  •   
git remote add -f infochimps git://github.com/infochimps/cluster_chef.git
  
      
  • 执行合并
  •   
git merge -s ours --no-commit infochimps/master
  
      
  • 仅将infochimps/cookbooks/cassandra合并到cassandra
  •   
git read-tree --prefix=cassandra/ -u infochimps/master:cookbooks/cassandra
  
      
  • 提交更改
  •   
 git commit -m 'merging in infochimps cassandra'

附录

奇怪, [编辑我] - 但read-tree步骤可能会失败:

  

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

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

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

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

答案 1 :(得分:22)

对于我的例子,假设你有一个分支来源'和分支机构的目的地'它们都反映了它们自身的上游版本(或者不是,如果只是本地版本)并被拉到最新的代码。让我们说我希望repo中的子目录名为newFeature,它只存在于' source'分支。

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

与我见过的其他所有内容相比,这些内容更加复杂,found here

请注意,这不是一个真正的合并'因此,您无法在目标分支中获得有关newFeature的提交信息,只需修改该子目录中的文件。但是,由于您可能会稍后将整个分支合并,或者将其丢弃,这可能不是问题。

答案 2 :(得分:6)

考虑到OP具有两个分支的情况,但只想将 dir-1 的历史记录从 branch-a 合并到 branch-b < / strong>:

# 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

答案 3 :(得分:3)

我从Eclipse的forum thread得到了这个,它就像一个魅力:

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

答案 4 :(得分:0)

create git repo包含branch-a和branch-b

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

答案 5 :(得分:0)

使用git log选择所需的提交,仅合并这些提交。这里的关键技巧是以简单的方式获取这些提交(这样您就不必通过手动检查git日志并手动输入它们来弄清楚它们)。方法如下:使用 git log ^<commit-a> <commit-b> --pretty=format:"%h" --reverse -- <subdir> 打印提交的sha1 id,如下所示:

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

commit-a是紧接在要合并的分支的起始点之前的提交,commit-b是要合并的分支上的最后一次提交。 --reverse以相反的顺序打印这些提交以供稍后樱桃选择。

然后这样做:

hitTest

两个步骤,简单而稳定!

答案 6 :(得分:0)

案例 0:我还没有接触文件

git checkout origin/branch-with-the-code-you-want ./path/to/dir1

这会为您提供其他分支上未暂存更改的文件夹。

案例 1:团队有干净的提交

如果您的团队执行干净的提交,那么在提交历史中挖掘可能会很有成效。在这些情况下使用 git cherry-pick COMMIT_HASH。如果需要,您可能希望 git rebase -i HEAD~N 其中 N 是一些提交,以将它们添加为历史记录中的 pick COMMIT_HASH 行。

案例 2:干净提交并不重要,但了解冲突很重要

如果您到处都有所有提交,那么您可能不需要保留历史记录,这是一种适用于这些情况的方法。请注意,这种方法不会删除文件或为您提供历史记录,但会为您提供每个文件之间的冲突。

# Create an orphan branch with no history but your files
git checkout --orphan temp-branch

# Get the version of the files from the other branch
git checkout origin/branch-with-the-changes ./path/to/the/folder/you/want/to/merge
git commit -m "Commit that has all files like they are on your branch, except that one folder you want to merge"

# Merge the other file tree
git checkout your-branch
git merge temp-branch --allow-unrelated

# Clean up
git branch -D temp-branch