My typical Git workflow.

Git is a powerful version control system and one of my favorite tools for a long time.

My idea here is not explaining the basic concepts about Git but just to show how I typically use it in my daily work. What I will illustrate here is also known as the branching workflow.

So, let’s start creating a hypothetical project to list, for example, the products of a shop.

1
mkdir myshop && cd myshop

Just to have a start point, let’s create a new app.rb file, init our repository and commit it to the master.

1
2
touch app.rb
git init

I will do here some very simple Ruby code just as example.

Let’s edit our app.rb:

1
2
require 'sinatra'
require 'sinatra/json'

then save it, and add to our repository:

1
2
git add --all
git commit -am "Initializing the main app file to handle our requests using the ruby framework Sinatra version 1.0.1"

Look to the message I used on my first commit here. "Initializing the main app file to handle our requests using the ruby framework Sinatra version 1.0.1"

It’s a meaningful commit message and can tell a lot about what I’m doing at this point on my project.

There’re some things I like to think about and answer when I’m writing a commit message:

  • What I’m doing.
  • Why I’m doing it.
  • What’s next.

Try to avoid messages on your commit like adding a new app.rb file. It’s tell nothing about your project history and will not help your teammates.

To create my branch, I use my initials as the prefix to naming it.

1
git checkout -b tf-new-products-feature

Since we’re now at the new tf-new-products-feature branch, then let’s add more some code to our app.rb

1
2
3
4
5
6
7
8
9
10
11
12
PRODUCTS = [{
title: "t-shirt",
size: "L"
},
{
title: "t-shirt",
size: "XL"
}]
get "/products" do
json(PRODUCTS)
end

If you want to run the code above, just install the gems gem install sinatra sinatra-contrib --no-ri --no-rdoc and run ruby app.json on your terminal.

After saving our file, we’re ready to commit the code by running a git commit like:

1
git commit -am "listing all products using the new /products endpoint"

And it’s should works fine.

Now my feature is completely isolated from the master branch, and I can switch over my master and others branches to work on some others tasks.

If you want, you can check it on your terminal:

1
2
3
4
5
6
7
8
cat app.rb
# will show the last updates we written.
git checkout master
# go to the master branch
cat app.rb
# will have just our initials requires.
git checkout tf-new-products-feature
# then let's back again to our branch

Sometimes I also want to keep an unfinished code where I’m still working and mark it as a “WIP” on my commit message. Also, it’s good to describe where I stopped and what I need to do next, like for example “WIP: created the endpoint to the new products. Needs to integrate to some DB.”

Let’s see it in practice editing again the app.rb file.

1
2
post "/product" do
end

then

1
2
git add --all
git commit -m “WIP: created the endpoint to the new products. Needs to integrate to some DB."

If I run a git log --oneline now, I will see my commits history

1
2
3
25c0fda WIP: created the endpoint to the new products. Needs to integrate to some DB.
6f96b03 listing all products using the new /products endpoint
c4b27b4 Initializing the main app file to handle our requests using Sinatra

If you have some remote repository, like on Github, you can send the branch to your remote repository by running:

1
git push -u origin tf-new-app-feature

It’s also a good idea to ask for feedback to the others teammates if you need some help on your WIP branch using a PR on Github. I did it many times and was always nice to get some other point of view and suggestions.

So, after got everything done, probably I won’t need to preserve the WIP commit on my history, and to discard or edit the commit message I will use the rebase in the interactive mode to squash or modify the commit message.

Let’s try for example to squash and also discard that commit’s log message.

1
git rebase -i HEAD~2

It’s should open to you something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pick 6f96b03 Listing all products using the new /products endpoint
pick 25c0fda WIP: created the endpoint to the new products. Needs to integrate to some DB.
# Rebase c4b27b4..25c0fda onto c4b27b4 ( 2 TODO item(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

To do what we need here, we just need to change the second line to f or fixup

1
2
pick 6f96b03 Listing all products using the new /products endpoint
f 25c0fda WIP: created the endpoint to the new products. Needs to integrate to some DB.

and then save and close the editor :wq!.

If everything goes fine, then we should see something like:

1
2
3
[detached HEAD 8026973] listing all products using the new /products endpoint
1 file changed, 18 insertions(+)
Successfully rebased and updated refs/heads/tf-new-products-feature.

And now, in our history, we will have only the previous message with that WIP discarded from our log history.

1
2
8026973 listing all products using the new /products endpoint
c4b27b4 Initializing the main app file to handle our requests using Sinatra

and on the app.rb, our work done before are also there:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
☺ cat app.rb
require 'sinatra'
require 'sinatra/json'
PRODUCTS = [{
title: "t-shirt",
size: "L"
},
{
title: "t-shirt",
size: "XL"
}]
get "/products" do
json(PRODUCTS)
end
post "/product" do
end

So, after everything done, probably we can merge our work into the master.

1
2
git checkout master
git merge tf-new-products-feature

And then, delete our branch locally and also remotely.

1
2
3
4
#delete locally
git branch -d tf-new-app-feature
#deleting remotely
git push origin :tf-new-app-feature
avatar

Tailor Fontela

Software Developer. Full-time apprenticeship.