Probably most people who use git know about patch management and whatnot, so I’m writing this largely for myself as I keep forgetting (mostly because I don’t have to do it very often).
Some code that I’m working on has a development branch which I’m working on while other fixes are being made to the master branch. This is great, except for the fact that I need to apply any changes made to master to the development branch as well (we’ll call it “feat/X”). And since I’m the only one working on feat/X, but others add fixes or necessary changes to master, I need to apply those changes. Some changes will apply clean, others need to be modified due to one part that is receiving a major overhaul.
There is probably a better way to do this and if so, please do let me know in the comments. Even though I use git almost daily, I am by no means a power user and would love more “insider tips”.
So I have my working copy, and I need it to know about both branches. By default, if you clone the repository you’ll just be on the master branch. So in this case I would have to
git checkout feat/X. Once I do that, I will see:
% git branch * feat/X master
So do a
git checkout master to switch back to the master branch. From here we can make a series of patches that represent code changes made to master after feat/X was branched:
% git format-patch feat/X
The first time you do this, all the patches will be new. But as you move along, you’ll continue to see these patches show up so it’s useful to keep them kicking around so you know which are new. You’ll see patches in the format “0001-The-commit-text.patch” and “0002-Other-commit-text.patch”.
I move the patches out of the way (I have horrid file management, so I just
mv *patch ~/). Then
git checkout feat/X to switch to the feat/X branch. Now we apply the patches one-by-one:
% git am <0001-The-commit-text.patch
If the patch is successful, you can do the same to the next. If not, however, you need to fiddle with things a bit. You’ll see an error like this:
% git am <~/0001-The-commit-text.patch Applying: The commit text error: patch failed: something/else.py:559 error: something/else.py: patch does not apply Patch failed at 0001 The commit text The copy of the patch that failed is found in: /home/vdanen/my-git-repo/.git/rebase-apply/patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort".
You can run
git am --abort which will revert the commit attempt, to allow you to manually apply the patch and commit. You can also use
git am --skip to do the same. I suspect if you fed git something like
git am <~/*patch these commands would mean different things (abort the session versus skip the one patch) but if you’re doing one patch at a time they both do the same thing.
You can also check the log output with
git log master..HEAD --stat which will show that our branch contains the update, along with the appropriate author information (might be you, might be me, might be someone else). I tend to skip the log bit and just apply one patch at a time. Rinse and repeat.
Finally, if you don’t move your patches like I did, you can use
git clean to remove the patches from your working directory. Use ‘-n’ first though, so it runs in dry-run mode.
Like I indicated earlier, there are probably simpler ways to do this, but this works for me. I got all of this from Ry’s Git Tutorial on Patch Workflows. Excellent tutorial.