A solid Git pull request workflow will keep you from having issues when
contributing work to projects of interest. At the core, the idea is
simple: keep a local master
branch simply as a means of getting the
latest official updates from the project's official Git repo so that you
can create new branches from it to work on your desired changes. Then,
always open PRs from these new branches, and once the PR is merged into
the official Git repo, you can simply move back to master
, pull those
official changes, and then checkout a brand new branch for the next item
you wish to work on.
git checkout master
git pull upstream master # get latest official updates onto your laptop
git checkout -b my_cool_new_branch # some new branch to work on a new project
.... # work on stuff (i.e. `git add -u`, `git commit -m "My latest work commit changes...."`, etc.)
git push --set-upstream origin my_cool_new_branch # push this branch to your GitHub so that a PR can be opened
.... # wait for it to be merged
.... # repeat above process
In general, this workflow will prevent most Git issues in the future.
In summary, (1) always keep master
fresh and based solely on the
official upstream git repo, (2) always create new local branches off of
master
, and (3) never merge local changes back into master
.
The only other piece you need to know is how to pull changes from the
official upstream repo onto a local PR branch that you've been working
on while other upstream changes are happening, if needed. The scenario
in which this is necessary is as follows: you use the above workflow,
but while you're working on my_cool_new_branch
, someone else has a
bunch of changes merged into the upstream official master that happen to
cause "conflicts" with you work. When this happens, your PR won't be
able to be merged. To fix this issue, all you have to do is "rebase"
your local my_cool_new_branch
work on top of the latest changes from
upstream master
, and then force push these changes to update your PR.
git checkout master
git pull upstream master # get latest official updates onto your laptop
git checkout -b my_cool_new_branch # some new branch to work on a new project
.... # work on stuff (i.e. `git add -u`, `git commit -m "My latest work commit changes...."`, etc.)
git push --set-upstream origin my_cool_new_branch # push this branch to your GitHub so that a PR can be opened
.... # wait for it to be merged
.... # CONFLICTS!!! Oh nooo!
git pull --rebase upstream master # this will pull latest changes, then "replay" your changes on top one-by-one, pausing if there are issues
.... # follow prompts if it pauses and says stuff must be fixed -- i.e. look for `<<<<<` & `>>>>` sections in the broken files and fix them
.... # once a file is fixed, `git add FILENAME`, then `git rebase --continue`, as it says on the prompt, which you can see again with `git status`
.... # repeat until it says rebasing is complete
git push --force # your local `my_cool_new_branch` is now technically different than that on your GitHub, so overwrite the latter
.... # the PR will be updated
.... # repeat as necessary until work is complete and PR is merged
The key here is that as your local commits are being "replayed" on top
of the latest official commits, the rebasing will pause and alert you to
conflicting files, with instructions on how to fix them. You can always
view this again with git status
. Basically, you'll just need to (1)
open the files that are conflicting, (2) search for the sections that
are conflicting (flanked by <<<<
and >>>>
markers), and (3) update
these sections to exactly how you wish them to be moving forward. Once
this has been completed for all conflicting files in the current stage,
simply git add -u
those files, and continue with the rebasing via
git rebase --continue
, both of which are mentioned in
git status
when this problem occurs. After possibly repeating this
process for other commits, eventually the rebasing will be complete,
and you can force push your changes to update the PR via
git push --force
.
See the following Gists that we (the committers) use for the SystemML project: