Recently I had an issue where I was given a patch for an assignment, as the professor had changed the code to add new functionality. Unfortunately, I had already put the original codebase in git and had made lots of changes and commits already. The workflow I used to apply the patch is as follows:
git checkout <hash_of_where_patch_should_go>
git checkout -b patch_branch
git apply patch
git add ./* && git commit -m "applying patch"
git rebase master patch_branch
//Fix merge conflicts
git rebase patch_branch master
This worked wonderfully, but my question is this: is this the 'correct' way to perform such a task? It seems to me like there must be a more straightforward way.
Keep a separate branch for the unmodified upstream code
Create a branch where you put the code as it is released by your professor. In your case, that will probably mean:
git checkout -b upstream <commit_where_you_imported_professors_stuff>
Apply patches from upstream only to the upstream branch
When your professor gives you a patch to his (her?) code, you will then checkout your upstream
branch, and apply the patch there – this should always be possible without conflicts.
git checkout upstream
git apply <whatever>
git add -A
git commit -m 'Patch from upstream'
Branch your own work off upstream
, and merge when needed
Now, to start adding your own work, you will branch upstream
, and commit to that branch. In your case, this has already happened, because you're already working on the project.
git checkout -b my_work upstream
... work ... work ... work (no play)
git add <stuff>
git commit -m 'Work done'
When you have to modify upstream
(the "framework" given to you by professor), you do it as described above (checkout, patch, commit), and then merge it into your work branch:
git checkout upstream
... patch upstream ...
git checkout my_work
git merge upstream
This way, you will get the following benefits:
- It's clearly visible to you on the
upstream
branch what the current state of the framework is, and which patches have been given to you, and when.
- When you have to patch
upstream
and merge it with your own work, it's easy to back out of this step if things go wrong (just do git merge --abort
or remove the merge commit).
- It's easy to see for you when during the course of the project you had to merge from Professor and which changes (and possibly merge conflicts on your work branch) that introduced.
- (Optional, not always useful) If you make your own patches to the framework, you can make them on the
upstream
branch (instead of your "work branch"), which will make it easier for you to display (diff
) them later on. You can think of those commits as your own upstream patches, living alongside those of Professor.
DON'T use "rebase" for that
I strongly advise against doing "rebase", because you will effectively destroy important history information (many comparison operations become difficult or impossible if you do rebase
ing instead of merge
ing).
Only use rebase if you have trivial (usually one-commit) changes that you need to merge, and want to avoid creating a merge commit.
Paul Stadig wrote a good piece about this topic (rebasing vs. merging): Thou Shalt Not Lie: git rebase, amend, squash, and other lies
Assuming it's not simpler to just apply the patch and deal with any rejects directly, I'd
git checkout $patch_base
git apply --index patch
git commit -m'patch from prof'
git checkout @{-1}
git cherry-pick @{-1}
# or git merge @{-1}