How do I merge a sub directory in Git?

Viewed 99653

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"?

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.

8 Answers

Given the OP's scenario where they have two branches, but want to merge only the history of dir-1 from branch-a into 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

Case 0: I didn't touch the files yet

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

This gets you the folder as it is on the other branch as unstaged changes.

Case 1: Team has clean commits

If your team does clean commits, then digging around in the history for the commits could be fruitful. Use git cherry-pick COMMIT_HASH for those cases. You might want to git rebase -i HEAD~N where N is some number of commits to add them as pick COMMIT_HASH lines in the history if you need to.

Case 2: Clean commits are not important, but knowing the conflicts is

If you have all the commits all over the place then you likely won't need to keep the history, here's one approach that works for those cases. Note that this approach will not delete files or give you the history, but it will give you the conflicts between each file.

# 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

The easy workaround, merge and reset the undesired changes, keep what you want

  1. You have a repository with directory structre git/src/a, git/src/b, you only want to merge the directory b
  2. git merge origin/a-feature-branch
  3. backup the the b directory changes, for example mv b b-merged
  4. reset the branch by command git reset HEAD --hard
  5. override the b directory with b-merged, mv b b-origin; mv b-merged b;
Related