Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git subtree merge, but keep local changes?

Tags:

git

There is a branch on a 3rd party repo that I want to add as a subdirectory of my repo. I want to be able to make changes to that 3rd party code, maintain those changes in my repo, and still be able to get updates that were made to the 3rd party repo. In essence, I'm trying to create an overlay.

Following the guide here for subtree merging (which describes exactly what I'm trying to accomplish), I've created a remote that points to that 3rd party repo, created a local branch that references the remote branch I want, done a pull on that branch, and used read-tree to copy the local branch's contents in to a subdirectory in master.

I have committed and pushed changes (new files and edits to existing files) in this subdirectory to master. Changes have also been made to various files in the upstream branch. I've been able to pull the changes down to my branch. However, when I attempt to merge as follows,

git merge --squash -s subtree --no-commit <my_branch>

My local changes are overwritten by the changes upstream. The new files I created are removed and changes I've made to existing files are lost.

Am I doing something wrong or is that the expected behaviour? How can I keep my changes and still merge in changes from upstream?

like image 823
Naenyn Avatar asked Apr 03 '13 01:04

Naenyn


1 Answers

I do not believe that this is the desired behavior, however I just worked through a similar issue myself.

In my case, turns out the issue was that when the other developer originally added the subtree to the master branch, he added multiple subtrees all at once. This had the result of changing the SHA of the resulting commit.

In consequence, when I tried to do the subtree merge, git was unable to find a common parent. This had the end result of git assuming that everything in my local tree was intended to predate the code from the original repo, and upon merge completion the local changes were lost.

I got around this by doing a git log --oneline in the subtree's prefix directory, and identifying the first commit into the local repo.

Then,

git checkout -b <subtree>_merge <first commit SHA>
git merge --squash -s subtree --no-commit <subtree_remote/ref>
git checkout master
git merge <subtree>_merge

This should leave you with the same result you would expect to see from a successful subtree merge from the top.

like image 110
bpescatore Avatar answered Oct 15 '22 02:10

bpescatore