Git branching and merging workflow¶
Cheatsheet¶
Do not use this cheatsheet if you haven’t read everything below.
We will assume your branch is called my-branch.
git checkout master
git pull
git checkout my-branch
git rebase -i --autosquash master
git push --force-with-lease origin my-branch
git checkout master
git merge --no-ff my-branch
git push
High-level overview¶
In general, we do most of our work in topic branches. They start off master and get merged back when they are tested and reviewed.
Before merging, a branch should be rebased on the latest master and merged
with --no-ff to create a merge bubble (useful for understanding history
and reverting the whole branch).
o [master] {origin/master} {origin/HEAD} <v3.6.dev5> Bump version: 3.6.dev4 → 3.6.dev5
M─┐ Merge branch 'review-person-sets-queries'
│ o [review-person-sets-queries] GPF-1562 clean up
│ o GPF-1562 fix handling of person sets collection queries
│ o GPF-1562 person sets clean up
│ o GPF-1562 reorganization of handling of person sets
o─┘ Bump version: 3.6.dev3 → 3.6.dev4
The branch naming convention we use is word-separating-dashes (AKA “kebab-case”). Don’t be afraid to write a long descriptive branch name.
Here’s the high-level overview of full cycle:
Create a new branch from the latest master and push it to GitHub.
Do work in that branch. Rebase on the upstream occasionally:
git fetch git rebase origin/master
and push often.
After rebase you’ll have to force push, but be careful to do so only with your branch. Use
--force-with-leaseto avoid orvewriting teammates’ work:git push --force-with-lease origin topic-branch
When you have to force push after rebase make sure that you notify your teammates, that work on the same branch.
Before merging the branch should pass through all tests and code review.
Open a pull request and ask someone of your teammates to review your code.
Once you’re done with the above, you can merge it in master.
Warning
Do not force push in the master branch.
Always when you plan to run git push –force-with-lease double check that you are doing it on the correct branch.
DO NOT FORCE PUSH IN THE MASTER BRANCH.
Merging into master¶
When you are ready with your topic-branch development you have to merge your work into master. The typical workflow is as follows:
First, rebase your topic branch with master:
git fetch git rebase -i --autosquash origin/master
If you have pushed your topic-branch before, you will have to force push it. Make sure you’re force pushing only the topic branch and not any of the others. It’s important to force push before merging into master, to enable github to detect the merge and mark the pull request as merged:
git push --force-with-lease origin topic-branch
Run the test cases locally and make sure they pass before you continue.
Merge your branch in master with
--no-ffCheck the commit history and make sure it looks OK (see the graphs below) before push.
Push the master branch, If someone has pushed into master before you, you will have to start the process from step 1.
Delete your branch from Github. Go to your PR’s page and click the “Delete branch” button at the bottom.
DO NOT use Github’s merge button. While it does a non-fast-forward merge, it does not rebase for you.
Note
As a high-level advice - master git on the console and do not rely on external tools for trivial tasks.
Note
In case you have forgotten to push your topic branch after the rebase (step 2.), your PR will not be closed automatically and you need to do this manually instead. For that purpose, please visit your PR page, leave comment- to mention that this branch was merged to master and then close the PR manually.
Rebasing and merging with –no-ff¶
Rebase before merging, because this provides a clean, linear history that’s easier to understand. Merge with –no-ff, because it creates a merge commit that:
makes it easier to see which commits belong to which topic branch;
can be easily reverted.
Multiple developers on the same topic branch¶
If you are not alone on given topic-branch you should be extra careful.
When you want to pull your teammates work from github you should use –rebase option:
git pull --rebase
This will rebase your work on your teammates work. After that you can push your work to your topic-branch:
git push origin topic-branch
The rebase of the topic-branch onto master should be coordinated with your teammates.
Note
Before rebasing topic-branch on master make sure that all your teammates have commited and preferably pushed their changes into the topic-branch. If there are changes that are not ready for commit/push, then this changes should be saved (probably stashed).
One of the teammates should do the rebase and force push:
git fetch
git rebase origin/master
git push --force-with-lease origin topic-branch
All other teammates should be extra careful when geting changes from the githbub. The preferable workflow is:
git switch topic-branch
git fetch
git reset origin/topic-branch --soft
Note
Please note that the reset command .. code-block:: bash
git reset origin/topic-branch –soft`
will remove your uncommited changes. Make sure that before starting rebase on master all you changes in topic-branch are commited or saved otherwise.
Merging without rebasing¶
Occasionally, there would be a rebase that’s hard to do and you will prefer making a merge commit. This can happen if a file has changed multiple times in the upstream, and multiple times in your topic branch – rebasing will make you resolve conflicts on each commit, while merging will make you resolve the conflict only once.
Make a fair attempt on rebasing, before you fall back to this option.
Examples: rebasing and merging with –no-ff¶
Suppose you branched off master and made two commits. While you’re working, somebody pushed a commit to the upstream master. Currently the repo looks like this (as shown by git log –oneline –graph –decorate –all):
* 2fd3cf7 (master) Upstream commit made after you started working
| * 4fc156a (topic-branch) Your second commit
| * c5b9fed Your first commit
|/
* 9413e7e The point you branched off
* eb18920 An earlier commit
At this point you should do something like:
git checkout master
git pull
git checkout topic-branch
git rebase master
git push --force-with-lease
git checkout master
git merge --no-ff topic-branch
When finally merged, your history should look like this:
* 53721b1 (master) Merge branch 'topic-branch'
|\
| * 0331a66 (topic-branch) Your second commit
| * a24e9bc Your first commit
|/
* 2fd3cf7 Upstream commit made after you started working
* 9413e7e The point you branched off
* eb18920 An earlier commit
Note that the SHAs of your commits have changed.
Your history SHOULD NOT look like this (it would happen if you forgot to rebase):
* cf96565 (master) Merge branch 'topic-branch'
|\
* | 2fd3cf7 Upstream commit made after you started working
| * 4fc156a (topic-branch) Your second commit
| * c5b9fed Your first commit
|/
* 9413e7e The point you branched off
* eb18920 An earlier commit
It SHOULD NOT look like this either (it would happen if you forget
to pass --no-ff):
* 0331a66 (master, topic-branch) Your second commit
* a24e9bc Your first commit
* 2fd3cf7 Upstream commit made after you started working
* 9413e7e The point you branched off
* eb18920 An earlier commit