I have 2 git branches branch1 and branch2 and I want to merge file.py in branch2 into file.py in branch1 and only that file.
In essence I just want to work on the file.py in branch1 but want to take advantage of the merge command. What is the best way to do this?
The simplest solution is:
git checkout the name of the source branch and the paths to the specific files that we want to add to our current branch
git checkout sourceBranchName pathToFile
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
.
What I've done is a bit manual, but I:
revert
;HEAD~1
, that is, their state in the
merge commit;Ugly? Yes. Easy to remember? Also yes.
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
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
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.
If you only care about the conflict resolution and not about keeping the commit history, the following method should work. Say you want to merge a.py b.py
from BRANCHA
into BRANCHB
. First, make sure any changes in BRANCHB
are either committed or stashed away, and that there are no untracked files. Then:
git checkout BRANCHB
git merge BRANCHA
# 'Accept' all changes
git add .
# Clear staging area
git reset HEAD -- .
# Stash only the files you want to keep
git stash push a.py b.py
# Remove all other changes
git add .
git reset --hard
# Now, pull the changes
git stash pop
git
won't recognize that there are conflicts in a.py b.py
, but the merge conflict markers are there if there were in fact conflicts. Using a third-party merge tool, such as VSCode, one will be able to resolve conflicts more comfortably.
You can stash
and stash pop
the file:
git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop
To merge only the changes from branch2's file.py
, make the other changes go away.
git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip
Merge will never even look at any other file. You might need to '-f' the checkouts if the trees are different enough.
Note that this will leave branch1 looking as if everything in branch2's history to that point has been merged, which may not be what you want. A better version of the first checkout above is probably
git checkout -B wip `git merge-base branch1 branch2`
in which case the commit message should probably also be
git commit -m"merging only $(git rev-parse branch2):file.py into branch1"
I am in same situation, I want to merge a file from a branch which has many commits on it on 2 branch. I tried many ways above and other I found on the internet and all failed (because commit history is complex) so I decide to do my way (the crazy way).
git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge
Source: Stackoverflow.com