Home > OS >  How to cherry-pick and merge only a subpath from a feature branch to master
How to cherry-pick and merge only a subpath from a feature branch to master

Time:11-25

I have an interesting problem (at least to me.)

I have a master branch and a feature branch, which has been parted its way from master a while ago. Another team keeps updating the master branch and my team is only working on feature branch.

The master branch includes some changes that my team is not interested in. We only care about their app folder, that's it. Even in the app folder, we are not interested in everything, only the changes that we think we need. We are not merging our feature branch into their master because there is tech-stack changes that we are implementing and only thing we need from them is their JavaScript code.

Meanwhile, we are also making changes in the feature branch's app folder. So in the app folder, they have some changes that we don't have, we have some changes that they don't have. We want to keep all our changes, but only pick some of their changes.

How can I go about merging their master branch's app folder into our feature branch's app folder? I have been researching for hours, tried some VS Code extensions to preview the difference between the two folders. What I am looking for is an interface where I can Accept or Decline everything that comes from master branch's `app folder. Although this is my preference, I am open to any suggestions that would solve this problem.

This may sound like a messed up situation but my team lost some members over the past couple of months and the difference between branches grew bigger and bigger every week. Now we want to solve this once and for all.

Thanks for your help.

CodePudding user response:

What I am looking for is an interface where I can Accept or Decline everything that comes from master branch's app folder

git checkout -p master app is crude but stands a decent chance of serving here.

If that's not showing you enough to decide what you want, the next step up is a selective merge with

git diff --merge-base @ master -- app | git apply -3

which will use Git's automerge machinery and leave any overlapping or abutting changes for you to sort out as usual, or you can save the diff to a file and edit it to taste before applying it if you're careful.

CodePudding user response:

There are two ways to do this. The simpler one will keep the changes, but discard any commits they made. The more complex one will preserve commits.

Recommendation

Both of the two methods discussed below have the potential to cause merge conflicts and other headaches down the line, especially as people continue to make changes on the master branch. Furthermore, if you have changes to the app/ folder in the feature branch, directly using git apply may result in your changes being overwritten.

I would strongly recommend merging the master branch into the feature branch via git merge with no squashing. Given the divergence you mentioned, there may be merge conflicts, but this is OK. Merge conflicts do what you want: they let you choose which changes to accept, and which to reject.

That being said, here are two approaches that are analogous to cherry-picking only a single folder.

Option 1: Discard commits, keep changes

This approach is pretty straight-forward, and it uses a combination of git diff and git apply:

git switch feature
git diff feature..master -- app | git apply --index

This will:

  • Switch to the feature branch (this is where you'll apply the changes)
  • Get all the changes made to the master branch, that aren't on the feature branch.
  • Filter only the changes in the app directory
  • Apply the changes via git apply
  • Stage the changes by adding them to the index (this is what the --index option does)

The only downside of this approach is that it won't preserve history, or commit messages.

From there, you can commit the changes yourself:

git commit -m "Apply changes made to master branch"

Option 2: Get both commits and changes

This one is a bit more complicated, and it relies on git format-patch.

git switch feature
git format-patch --stdout feature..master -- app | git am

This will:

  • Switch to the feature branch (where you'll apply the changes)
  • Get all the changes made to the master branch, that aren't on the feature branch
  • Filter by only the changes made in the app directory
  • Format these as a series of patches (containing commit messages, authors, etc)
  • Apply all of these patches using git am

Note that depending on the contents of changes, this may result in a failure that you'll have to resolve manually. (It'll alert you to this)

  • Related