Note: this is a summary of different git workflows putting together to a small git bible. references are in between the text
Try to keep your hacking out of the master and create feature branches. The feature-branch workflow is a good median between noobs (i have no idea how to branch) and git veterans (let's do some rocket science with git branches!). Everybody get the idea!
- I need a new feature in my awesome software project:
git checkout -b f/better-than-before
- I found a bug! I need to fix that (bug fix)
git checkout -b b/weird-error
- I found a bug! I must do a workaround (hot fix)
git checkout -b h/weird-error
- f/ (feature)
- b/ (bug fix)
- h/ (hot fix)
- Avoid staging multiple unrelated changes to the same commit (try
git add -p
to add specific lines) - Keep your first commit subject line short (about 50 chars)
- Use imperative Add instead of Adds, Added or Adding
- Use familiar keywords such as:
Add, Update, Remove, Fix, Refactor, Improve, etc
- If you made a typo, feel try to go
git commit --amend
to edit your message and add a missing filegit add folder/file
- Read more
master *---*---*-------* (master got new commits)
\
f/new-feature *---*---* (branched off 2 commits ago)
Think before you pull changes from origin or you're getting into trouble.
Stop using the standardized merge strategy for git pull
master *---*---*-------*
\ \
f/new-feature *---*---*---* (merge commit of master)
If you need an update from master or any other branch, try to rebase your branch instead of merging. Try to keep your branch history separated from master, so others can easily follow one straight line of commits.
master *---*---*-------*
\
f/new-feature --> *---*---* (f/new-feature on top of updated master)
So, if you want to pull, try
git pull --rebase
You may want to set that as default
git config --global pull.rebase true
Then you can only run
git pull
If you want to update your work with stuff from master
git fetch -a && git rebase master
If you're running into thousand of merge conflicts, try to merge, but do not merge in case of laziness!
If all hope is gone, use cherry pick as your last hope to get back to work. But use with wisdom! This is only for advanced users: further reading: cherry-pick vs. merge workflow
If you try to push your rebased branch, your remote will reject your command, because you changed the history of your branch. You need to do a force push and this is not exactly ideal.
git push origin +f/new-feature
Use the +
syntax, this will avoid you wrongly doing a git push -f
to and from another branch.
If other people work on that branch too, inform them about your rebase and check before pushing.
But if you really need to (just be sure of what you are going), a teammate can get up-to-date with the new rebased branch
First, make sure to branch out before to not lose his work
git branch f/new-feature
Then you guys can reset the local branch to perfectly match the f/common-feature-branch
on origin
(the one we forced updated)
git reset --hard origin/f/common-feature-branch
After resetting, he can put his work back on top of the new rebased branch
git checkout f/new-feature
git rebase f/common-feature-branch
Use the Squash and merge
button to keep your master branch clean.
master *---*-------*---*
\
f/new-feature *---*---*
[done by GitHub] git rebase -i HEAD~3
master *---*-------*---*
\
f/new-feature * (new squashed commit)
[done by GitHub] git merge master f/new-feature
master *---*-------*---*
\
f/new-feature * (master's HEAD is fast-forwarded to f/new-feature's HEAD)
[done by GitHub] git merge master f/new-feature --no-ff
master *---*-------*---*-----------* (merge commit, yikes!)
\ /
f/new-feature *---*---*
We want to prioritize a simple straight line of commit. Feature branches going into master/integration should be squash and merge. However, we should be doing merge commits when going between master
<-> integration
<-> big-feature-branch
as squashing squashed commits would squash too much commits losing our precious and detailed commit messages.
If you lost one of your commits, try use git log
and find your straying commit.
If your commit is still unrecoverable, use the lost+found feature of git
If you fucked up while going git rebase
, use git reflog
and git reset --hard <sha>
to a stable point