How should you commit your code?

How should you commit your code?

98 views

I've been using a version control system (mainly Github) for a quite long time, but I've only been using the basic features. So, I've been wondering "How am I supposed to use these like other people (read: pro)?", then I started to read a lot of articles and videos about using git.

Surely, there are so many things I don't know that somehow make me excited to learn. But then I wondered, "Have I done the basic things properly?" This question got me into "How should I commit my code? How often should I commit them? Is there any convention when writing commit messages?" So in this post, I will share what I've learned so far.

Oftentimes, we only focus on writing a lot of code and by the time we finished, we have a lot of code changes for various purposes or concerns. Let's say we have this code initially:

Copied to clipboard
export const sum = (a, b) => { return a + b; }; export const sub = (a, b) => { return a - b; };

Then we would like to 2 features:

Copied to clipboard
export const sum = (a, b) => { return a + b; }; export const sub = (a, b) => { return a - b; }; export const mult = (a, b) => { return a * b; }; export const div = (a, b) => { return a / b; };

When we're ready to commit these changes, often we just commit the whole thing.

Let's say our commit message looks like this

git commit -m "Add multiplication and division features."

From someone else perspective, it can be difficult to understand which changes do what, and other changes do other things. To prevent this matter, ideally, 1 commit should represent 1 logical change. Therefore, a better way to commit them is to separate the commits by their purpose. In this case, since we added 2 features, we would make 2 commits.

git commit -m "Add mutliplication feature."

and

git commit -m "Add division feature."

"But I've already made those features, does that mean I need to remove the other code first to make commits?"

No! You don't have to remove the other code. Instead, use the git features to select some part of your code to be staged using patch mode. There are two ways to do this, using patch flag git add --patch file or using interactive staging git add --interactive.

Let's use the first one. So I will reuse the code above and name the file as math.js and make the first code snippet (sum and sub) the initial state. I will also deliberately make typos the mult feature for simulation.

If we use git diff math.js, we will see this

We want to stage the file but not the whole thing, we only want to stage the mult

For that, we use

git add --patch math.js

It will show you a list of hunks. A hunk basically a part of the that has changed. In this case, we have one hunk (all the green text).

At this point, there are some actions you can do (commands are inside the square brackets). If you type ? and press enter, you will see the explanation of each command. But for our case, we need to separate the mult and div to separate commits. We can edit the hunk by typing e and pressing enter.

It will then show your git editor (I've configured my editor as vim), but regardless of your editors, it will look like this

We can now remove any part of the code we don't want to commit to our code. You can also see the description of what you can do.

Once we're done, we can save it.

Now back to the terminal, let's check the status

git status

You will see there are staged and unstaged versions of the same file.

Let's see the diff

git diff math.js

Now the hunks have changed. The mult part is not green. That means, the mult part has been staged and we're ready to commit it.

git commit -m "Add multiply feature."

We can make sure the commit by looking into the git log

git log

As you can see, the commit has been submitted. We can make sure and see what has changed in that commit

git show [commit SHA]

As you can see, you can easily know what has changed and know what logical things have been added/modified.

Let's try this once more. I will show how you can use interactive staging and split hunks. For that, I need to arrange the scenario lol.

The scenario will be

1. Add div feature and move it to the top line of the code (it's just to simulate splitting hunks since I can't think of another way at this point)

2. Fix multiply feature (remember that we use / instead of * lol)

So the code should look like this

Copied to clipboard
export const div = (a, b) => { return a / b; }; export const sum = (a, b) => { return a + b; }; export const sub = (a, b) => { return a - b; }; export const mult = (a, b) => { return a * b; };

Let's start patching using interactive staging

git add --interactive

You will see this prompt, and we want to apply patches. Therefore, we type p and press enter (you can see the description of each command using h as well)

Now select the file(s) we want to patch. In this case, we only want 1 file. We select the file by typing the number (in this case 1) and press enter

There's a mark (*) next to the number now. If you want to add more files you can redo the previous step. Once we're done, press enter

Unlike the previous example, we now have (1/2) at the bottom. These numbers represent current hunk and total hunks.

So what do we do now? We want to add this hunk and commit it as a new feature. To stage this hunk, we type y and press enter (for other command descriptions, type ? then enter).

It will then guide us to the next hunk. So remember, we don't want to include this as it doesn't correspond to our div feature. To ignore this hunk, type n and then press enter.

Once all the hunks have been reviewed, we will get to the menu

You can patch or add more files at this stage. This is useful when you have multiple files that correspond to the feature or logical change to your code, be it modified files or new files.

Once you've done this, you can quit by typing q end pressing enter.

As we've done previously, we will see staged and unstaged versions of the file. And yes, everything you added during the interactive staging will be staged and ready for commit.

Now we can commit

git commit -m "Add division feature."

Let's make sure we commit properly using git log and git show [commit SHA]

Now we have committed the changes properly. The last thing to do is to commit the fix for mult feature.

If we take a look at the diff

Since there's only one hunk and the changes are only for the fix, we can safely stage them all and commit them, so:

git add -A && git commit -m "Fix multiply operation"

If we take a look at the log:

git log --oneline

We have separated our commits based on what feature or logic we have changed. One commit per one logical change.

By separating our commits, someone else can catch up easily with what has changed and what the changes do by reviewing the commits.

There is a lot more I want to share regarding using git and I'm planning on writing a series of this.