LazyTyper
LazyTyper

Reputation: 3

git - merge two divergent branches ignoring some directories

Short story: I want to tell git to ignore a directory when merging. I know git doesn't work that way...

Long Story: I have a project that will be deployed on two different platforms. Every platform needs some tweaks to the code for the deploy.

I have two branches, one for every platform: PlatformA and PlatformB. The two branches are practically identical. The only difference is in a couple of files and a directory that needs to be present on one platform but not on the other. This is the scenario:

PlatformA branch:
 - dir1
   - file1
 - dir2
   - file2

PlatformB branch:
 - dir1
   -file1

The problem appears when I'm working on platformA and make changes to file1. I want these changes to also be available on platformB. The problem is when I do the merge, git adds dir2 and file2 to platformB.

I also want to be able to work on platformB and make changes to file1 and be able to merge to platformA without git removing dir2 and file2.

So the question is: There is any way to have two mergeable divergent branches? OR There is a way to tell git to ignore a directory/commit?

I have tried this solution but only works when merging ProjectB->ProjectA, not the other way around (git copies dir2 and file2 onto ProjectB).

Also, I think I can cherry-pick every time, but that just seems cumbersome and prone to erros.

Thanks in advance!

Upvotes: 0

Views: 354

Answers (4)

jthill
jthill

Reputation: 60403

Closest to familiar ways is to do the merge --no-commit --no-ff and undo anything you don't like about its usual behavior, e.g.

git checkout A
git merge --no-commit --no-ff B
git checkout @ dir2       # nope, didn't want dir2 gone
git commit

This is likely best when the usual command already does what you want except for a couple of little things, and you want to change as little as possible.

Another option: "what @Messa said". The setup he recommends and as he points out linux uses is a subdirectory per deployment target. This is likely best when you have (a) a free hand with your repo setup (b) an amenable build/test toolkit, and (c) it's at least somewhat reasonable to administer everything as a single project. That's a very common case, and for a small shop it's the first one I'd look at.

But if those cause trouble, or might cause trouble, the only one of the remaining options I'd pick is to administer dir1 separately, as a submodule. This comes with administrative overhead, it's far from a "just works" thing until you've spent the time to get yourself very confused and then find your way to mastery (by wrecking several toy repo's), but: the rituals aren't harder than crossing the street with your kids, you just do have to learn how to do it right, and it does offer one sterling advantage: it implements exactly what you want.

Upvotes: 1

twalberg
twalberg

Reputation: 62439

It's probably not ideal, but this is the approach I've used for a couple similar projects... Introduce a third branch, named core, for example. Do all your development that you want to be available on both platforms on that branch, and only do platform-specific development on the platform-specific branches. Periodically merge core into each of the platform branches (but not the other direction!). It can get tricky to keep track of which changes you want to put where, especially if you have a specific change to make that needs to be split into platform-specific and platform-agnostic parts, but it works as long as you remember to think about what you're doing. It can also be a pain when you add more platforms to keep track of...

Upvotes: 0

Messa
Messa

Reputation: 25201

I recommend to not use branches for platform specific files. Reorganize the project so that all platforms are together in a single directory tree and common files are present only once.

Like Linux kernel - it has arch directory with platform-specific code, not a bunch of branches.

What happens when you need to develop some new feature that's larger than just one commit? You create branches PlatformA-CoolFeature and PlatformB-CoolFeature? That would be a merge hell :)

Upvotes: 1

Juan
Juan

Reputation: 1794

I don't think there is a straight away nice and clean solution for this, but as a workaround you could play a little bit with the .gitignore files to accomplish that. If you include ./dir2/* in your .gitignore file, dir2 will never be merged neither from A to b nor from B to A, but if you modify files from that directory these files won't be tracked by git at all, unless you manually add them before committing.
Depending on how often you need to do each of the actions (modify dir2 in A / merge A into B) one or other solution could be more suitable, but I think you will always need to modify when swapping from one action to the other. You could have an script to modify the .gitignore file for you, in case you need to add or remove many directories from the repository.

Upvotes: -1

Related Questions