Shoeboxam
Shoeboxam

Reputation: 43

git merging branches that have been rewritten with shared files

I branched from master about a year ago, and the branch turned into a long-running second project. During this time, the same files underwent near-complete rewrites in each branch. I have now moved the codebase in the branch to its own folder, but upon merging there is a year's worth of conflicts for files used jointly by two separate projects.

Is the best solution to rewrite the entire history of my branch to use a different folder? How would I merge these two codebases together in separate folders?

Upvotes: 0

Views: 46

Answers (1)

Mark Adelsberger
Mark Adelsberger

Reputation: 45749

Is the best solution to rewrite the entire history of my branch to use a different folder?

That depends on whether, at this point, they are logically different files. If they are logically a single file - if changes for one project at worst won't hurt the other project's usage, and especially if the same change commonly benefits both projects - then you'll be better off maintenance-wise to merge them. But if a single file no longer serves both masters, then you'll have to split them - whether simply by renaming/moving one as you consider above, or by a more sophisticated refactoring if there's a reason (e.g. maybe some part of the file is still common).

So that is something you'll have to determine. If you do want to keep them separate, then rewriting one project's history to relocate the file is an option. It's conceptually straightforward, so that's the plus. The down sides are, it may break the historical versions of the project (since it may find the other project's file where it expects its file... unless you do a more thorough rewrite that updates each historical version to know that the file is moved), and if the repo is shared then all users will have to coordinate to update to the new history.

Now, if the code for the projects as a whole is so unrelated that it makes sense to just have each codebase in a separate folder, then you might want to consider keeping them in separate repos. For some reason "monorepos" have gained some popularity, but really it isn't the best use of git. To work on the tool's terms, you would let each repo be the home of one project (and, if there's a shared component, ideally move that to a 3rd repo and use either git submodules or build tooling to include that as a dependency of each project).

But if you decide still that you want to have the two projects share a history going forward, and coexist at different folders in shared commits, there are a couple ways to go about it.

As you note, you could try rewriting the branch's history. I'm not sure that will solve the problem, because any of these files that existed before you created the branch will still be observed as "moved" in the first commit of the branch. (Unless you also move it in the shared history that precedes the branch creation, in which case it will be seen as "moved back" in the next commit of the other branch...)

So instead you may just want to tweak how the merge works. Having moved the files to there future paths at the tips of their respective branches, you would initiate a merge but keep it from committing; get the work tree into the desired state; and then commit.

Assuming there are some files you literally intend to merge, then you can start the merge normally, because the conflicts will prevent the commit. Then as part of "conflict resolution" you would get the paths sorted out.

git checkout HEAD -- project-1-path
git checkout project-2-branch -- project-2-path

(where project-1-path and project-2-path are the file locations to which you moved the respective versions of the file in question, in the last commits to each branch before the merge).

Upvotes: 1

Related Questions