Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging subtree changes - fatal: invalid path 'somefile_BASE_20704.cs'

Tags:

I have three repos - names changed for clarity:

SharedStuff, ProjectA and ProjectB

Both of the projects are using git-subtree to maintain a local copy of SharedStuff. They both have made local changes that I'm trying to merge up centrally, test, then merge back out to each again.

I've run this on the ProjectA repo:

git subtree split --prefix=SharedStuff -b SharedStuff_from_ProjectA --rejoin

...then pushed that to the SharedStuff repo, resolved a few simple conflicts, merged it up.

Now I've run this on the ProjectB repo:

git subtree split --prefix=platform/SharedStuff -b SharedStuff_from_Project_B --rejoin

...and again pushed that to the SharedStuff repo in a new branch. The problem occurs when I'm trying to merge those changes in.

In the current case, I switch to the SharedStuff_from_Project_B branch, then git merge master - but I immediately get all changed files listed as add/add conflicts. When I run git mergetool, each one has an error like this:

Merging:
somefile.xyz

Normal merge conflict for 'somefile.xyz':
  {local}: created file
  {remote}: created file
fatal: invalid path './somefile.xyz_BASE_20704.cs'

(Of course, if I try the other way around - to merge SharedStuff_from_Project_B into master - I get the same kinds of conflicts, just reversed. Still add/add).

My guess is that something might be wrong in ProjectB's history, causing the appearance of add/adds. I'm not sure how to further diagnose this, though - what can I do?

Edit: there was a previous subtree "rejoin" commit in ProjectB, but the changes weren't merged into SharedStuff at that point it seems. But, re-running git subtree split with --ignore-joins produces the same problem - lots of add/add merge conflicts, despite the history of that split subtree branch going back to when the SharedStuff was first put into ProjectB. :(

Edit: Also git merge-base between the split subtree from ProjectB and master on SharedStuff doesn't give any results. I'm not sure how this came to be or how to resolve?

like image 902
Kieren Johnstone Avatar asked May 17 '16 08:05

Kieren Johnstone


People also ask

How do you push a subtree?

Adding a subtreeSpecify the prefix local directory into which you want to pull the subtree. Specify the remote repository URL [of the subtree being pulled in] Specify the remote branch [of the subtree being pulled in] Specify you want to squash all the remote repository's [the subtree's] logs.

How git subtree works?

A Git subtree is a replica of a Git repository that has been dragged into the main repository. A Git submodule is a reference to a particular commit in a different repository. Git subtrees, which were first introduced in Git 1.7. 11, help you make a copy of any repo into a subdirectory of another.

What is git subtree split?

Use git subtree split to extract the files you want to the an intermediate branch in your repository (you have already done this). git subtree split -P lib3 -b new-branch.


1 Answers

I do not know what caused this. However, here's how I resolved it - kind of. I still want a better answers!

Both 'shared' branches the actual master on SharedStuff and the split-off copy from ProjectB had a the same commits in their distant history - well, the same changes with the same tree SHAs internally, but different commit SHAs. This is because, somehow, the ProjectB branch had a different very first initial commit than SharedStuff.

So long as there were no common commits (with the same SHAs) in the history, merging, rebasing etc won't be able to find a common ground and will assume files were added in both histories.

The solution: find two early commits in the history with the same tree SHA (i.e. exactly the same file content), and commit info - message, author etc - and manually 'overwrite' the parent of that commit in ProjectB's split branch to the parent in SharedStuff's master.

I did this using a graft: Setting git parent pointer to a different parent

  1. Write a new line to .git/info/grafts, basically wrong-parent right-parent
  2. Switch to the branch - discover PowerShell echo used a 16-bit character format, re-save with Sublime Text and switch again ;)
  3. Run git filter-branch right-parent..HEAD on the branch to seal the deal
  4. Verify everything's mergeable

The next fun challenge will be seeing how this version merges back into ProjectB; will update when that's done..

I would still really welcome a real answer to this - this is really hacky!

like image 149
Kieren Johnstone Avatar answered Oct 07 '22 21:10

Kieren Johnstone