Last active
September 16, 2022 17:51
-
-
Save briangordon/02c2d2dc52825f0673b74beca2b8b1c1 to your computer and use it in GitHub Desktop.
Aliases for code reviewing GitHub pull requests using a GitFlow/OneFlow branching model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
***************************************************************************************************************************** | |
Introduction | |
The code review workflow that I prefer is to check out a feature branch, then `reset --soft` to move the branch HEAD to | |
just before the changes. That way I still have all of the changes in my working copy, and those exact changes are staged | |
for commit. My IDE will highlight the changed lines right in the editor and let me click the gutter to view a quick diff. | |
This is incredibly useful. But problems arise when develop has been merged into a running PR, bringing along a whole bunch | |
of other unrelated changes that have already been reviewed. I don't want all of those other changes to be highlighted in | |
my IDE, but I do want them in my working copy. | |
GitHub's "Files changed" tab handles this perfectly. It only shows the files relevant to the pull request. If at some point | |
in the PR's history someone has clicked the button to auto-merge develop into the feature branch, none of those merged | |
commits affect what appears in "Files changed" unless the merge commit also includes a manual conflict resolution fix. | |
Unfortunately, this has been tedious to reproduce locally, especially for pull requests with lots of merges. | |
Below are two git aliases which will set up this scenario in your working tree automatically. | |
***************************************************************************************************************************** | |
Usage | |
* git review pr-number [base-branch] | |
This alias loads up GitHub pull request number $pr-number into your working tree. Your working copy and index are set | |
to the contents of the latest commit in the pull request, and all relevant changes are staged for commit. You can | |
optionally provide $base-branch if the PR is merging somewhere other than to the default (develop). | |
* git review-merge pr-number [base-branch] | |
This is the same as the previous alias, but it will leave you in a merging state. This may be useful if you want to | |
commit the merge yourself and force push it to $base-branch bypassing GitHub's merge button. | |
***************************************************************************************************************************** | |
Installation | |
These two aliases come in TWO FLAVORS. You should choose one of the two flavors based on your preferences and copy the | |
corresponding alias definitions for that flavor to your ~/.gitconfig. | |
----------------------------------------------------------------------------------------------------------------------------- | |
| FLAVOR ONE (RECOMMENDED): Your working tree will be ALWAYS left in a detached head state. If you don't know what that | | |
| means then I recommend that you choose this flavor. | | |
----------------------------------------------------------------------------------------------------------------------------- | |
[alias] | |
review = "!sh -c 'pr=$0 && base=${1:-develop} && if [ \"$0\" = \"sh\" -o \"$2\" != \"\" ]; then echo \"Usage: git review pr-number [base-branch]\"; false; fi && git fetch origin \"$base\" && git fetch origin \"refs/pull/$pr/head\" && git checkout $(git merge-base \"origin/$base\" FETCH_HEAD) && git merge --squash FETCH_HEAD'" | |
review-merge = "!sh -c 'pr=$0 && base=${1:-develop} && if [ \"$0\" = \"sh\" -o \"$2\" != \"\" ]; then echo \"Usage: git review pr-number [base-branch]\"; false; fi && git fetch origin \"$base\" && git fetch origin \"refs/pull/$pr/head\" && git checkout $(git merge-base \"origin/$base\" FETCH_HEAD) && git merge --no-commit --no-ff FETCH_HEAD'" | |
----------------------------------------------------------------------------------------------------------------------------- | |
| FLAVOR TWO (ADVANCED): Your working tree will NORMALLY be left in a detached head state. However, it won't leave HEAD | | |
| detached at the same commit as your local $base-branch. Instead, it will re-attach HEAD to your | | |
| local $base-branch since it's there anyway. Beware that this can potentially be confusing if you | | |
| haven't git pulled and your local $base-branch is different from origin/$base-branch. | | |
----------------------------------------------------------------------------------------------------------------------------- | |
[alias] | |
review = "!sh -c 'pr=$0 && base=${1:-develop} && if [ \"$0\" = \"sh\" -o \"$2\" != \"\" ]; then echo \"Usage: git review pr-number [base-branch]\"; false; fi && git fetch origin \"$base\" && git fetch origin \"refs/pull/$pr/head\" && mergebase=$(git merge-base \"origin/$base\" FETCH_HEAD) && git checkout -f $mergebase && if [ \"$mergebase\" = \"$(git show-ref -s \"refs/heads/$base\")\" ]; then echo \"This PR already incorporates the latest changes from $base. HEAD is moving to $base.\"; git symbolic-ref HEAD \"refs/heads/$base\"; fi && git merge --squash FETCH_HEAD'" | |
review-merge = "!sh -c 'pr=$0 && base=${1:-develop} && if [ \"$0\" = \"sh\" -o \"$2\" != \"\" ]; then echo \"Usage: git review-merge pr-number [base-branch]\"; false; fi && git fetch origin \"$base\" && git fetch origin \"refs/pull/$pr/head\" && mergebase=$(git merge-base \"origin/$base\" FETCH_HEAD) && git checkout -f $mergebase && if [ \"$mergebase\" = \"$(git show-ref -s \"refs/heads/$base\")\" ]; then echo \"This PR already incorporates the latest changes from $base. HEAD is moving to $base.\"; git symbolic-ref HEAD \"refs/heads/$base\"; fi && git merge --no-commit --no-ff FETCH_HEAD'" | |
***************************************************************************************************************************** | |
Troubleshooting | |
If your GitHub remote is not named "origin" then you should rename it or find/replace in the alias definitions to substitute | |
your custom name. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment