Just recently I gave a presentation on Git (the version control system, not the British pejorative). I introduced newbies to the Git world and the concepts behind it and demonstrated advanced users some lesser known Git features.
Additionally, I introduced my personal workflow when working on small scale features, let’s say the size of one commit to the main line. Some of my colleagues found this workflow to be particularly interesting, so I’d like to share it here and discuss its benefits and drawbacks.
Since I trust the reader’s competent knowledge of Git basics, I will not explain any git commands in this blog post.
merge --squash
The workflow I’ll describe should only be applied to features that fulfill the following conditions:
Before we proceed, please remember this important advice from the Pro Git book:
Do not rebase commits that exist outside your repository.
If you follow that guideline, you’ll be fine. If you don’t, people will hate you, and you’ll be scorned by friends and family.
This simple rule also applies to any operation which changes commit hashes, e.g. commit --amend
, cherry-pick
, etc.
So now that we know what to do in order to keep our friends and family at peace, let’s get started with my personal workflow for working locally.
The basic (and simple) idea is to use a local, dedicated, temporary feature branch where you commit as often as you like until the feature is done. Then the result is merged into the main line as one commit without rebasing or any other major Git magic.
The important steps are printed in bold.
I’ll assume two things:
master
my_feature
The workflow itself is fairly easy once you have used it yourself:
my_feature
in this example) my_feature
my_feature
master
into my_feature
pull
beforehand master
master
with git merge --squash my_feature
my_feature
in the master's
staging area (merge --squash
doesn’t auto-commit)master
my_feature
I use this workflow because of the following reasons:
git stash
could be used but the stash can be deleted accidentally, e.g. git stash drop
).remote
my_feature
has been integrated into master
my_feature
after you merge --squash
and commit
to master
. At this point you know that everything has been merged.I am writing this blog as a single file which is version controlled in a local branch of a Git repository which also holds my presentation files. I have created a new branch for the work in progress and commit the text from time to time. However, in the end I want to have one commit for the blog entry, since I do not care how I got to the end result, I just want to save in between.
So here are my commits in my local branch blog
:
$ git log --oneline --decorate
53a53dd (HEAD, blog) Some last modifications
3c494d9 Add conclusion, remove more TODOs
f20e47b Remove TODOs
bebcc78 Benefits and Drawbacks
843b6e9 Finished workflow section
e3aa37c Some minor corrections
b47eec4 Add example
92009c7 Until benefits
7ee81bc First draft of blog
After the git merge --squash blog
on branch master
, as you can see, there is only one new file in the staging area:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: blog/blog.mdown
After committing the finished blog my history looks this way:
$ git log --oneline --decorate --graph --all
* 2281abe (HEAD, master) Git blog entry about 'merge --squash'
| * 2cca283 (blog) Updated example
| * 53a53dd Some last modifications
| * 3c494d9 Add conclusion, remove more TODOs
| * f20e47b Remove TODOs
| * bebcc78 Benefits and Drawbacks
| * 843b6e9 Finished workflow section
| * e3aa37c Some minor corrections
| * b47eec4 Add example
| * 92009c7 Until benefits
| * 7ee81bc First draft of blog
|/
* 25690aa (origin/master) Add PDF for latest version
The blog
commits (7ee81bc
through to 2cca283
) have been squashed into commit 2281abe
on master
.
If used responsibly, Git’s capabilities in rewriting history can be very helpful. The local merge --squash
workflow can safely store work-in-progress and hence protect your work from accidental modification or loss (this does not apply to git stash
for example, since you can always drop
the stash
).
As always, you don’t have to use this feature, Git just makes it possible for those who want to. So go ahead and try! It certainly changed the way I work locally.