Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge specific files from Git branches

Tags:

git

git-merge

People also ask

How do I merge individual files in git?

We can use git checkout for far more than simply changing branches. If we supply it with a branch name and a file, we can replace a corrupted or broken file. Instead, if we want to pass some of the changed content we can use the --patch flag to manually merge an individual file.

Can I merge specific commit from another branch?

Go to either the git log or the GitHub UI and grab the unique commit hashes for each of the commits that you want. "Cherry pick" the commits you want into this branch. Run this command: git cherry-pick super-long-hash-here . That will pull just this commit into your current branch.


When content is in file.py from branch2 that is no longer applies to branch1, it requires picking some changes and leaving others. For full control do an interactive merge using the --patch switch:

$ git checkout --patch branch2 file.py

The interactive mode section in the man page for git-add(1) explains the keys that are to be used:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

The split command is particularly useful.


Although not a merge per se, sometimes the entire contents of another file on another branch are needed. Jason Rudolph's blog post provides a simple way to copy files from one branch to another. Apply the technique as follows:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Now file.py is now in branch1.


None of the other current answers will actually "merge" the files, as if you were using the merge command. (At best they'll require you to manually pick diffs.) If you actually want to take advantage of merging using the information from a common ancestor, you can follow a procedure based on one found in the "Advanced Merging" section of the git Reference Manual.

For this protocol, I'm assuming you're wanting to merge the file 'path/to/file.txt' from origin/master into HEAD - modify as appropriate. (You don't have to be in the top directory of your repository, but it helps.)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

git merge-file should use all of your default merge settings for formatting and the like.

Also note that if your "ours" is the working copy version and you don't want to be overly cautious, you can operate directly on the file:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt

Are all the modifications to file.py in branch2 in their own commits, separate from modifications to other files? If so, you can simply cherry-pick the changes over:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

Otherwise, merge does not operate over individual paths...you might as well just create a git diff patch of file.py changes from branch2 and git apply them to branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

You can stash and stash pop the file:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

The solution I found that caused me the least headaches:

git checkout <b1>
git checkout -b dummy
git merge <b2>
git checkout <b1>
git checkout dummy <path to file>

After doing that the file in path to file in b2 is what it would be after a full merge with b1.