Here I will share the main points of what I Learned, about git commit history, good practices and how to achieve that using a dozen git commands. These things I learned in the last month, by doing a few hundred commits, with pair programming.
An accurate register of all commits, that contain the changes on files, there you can track what change and when, or compare the current version with the previous. Where do we see it? Type on git bash:
git log --oneline
If you have too many commits, you can navigate by commits messages, as you do in any file, using keyboard arrows or page up/down, to exit type (q), it’s a shortcut to quit.
Don't write meaningless messages, they should be short and self-explanatory, to say what changes you made in the code and where they take effect, for example:
An illustration of why we do this, imagine you are in a huge project, with so many collaborators, that you even don’t know who most of them are.
So you make your new feature, make the tests in your machine and all is working.
But when you push all sudden fails, so the first thing you want to check, is what are the changes made in the half time you are coding your new feature, and in the git log you got a lot commits with messages like “fix”... you can see how much waste of time will be to track down?
Commit with frequency, finished a function? Commit it, improved style of a single div? commit and so on. Ideally one file at a time.
You may think, why should I commit so many? The main reason is that your new functionality can break another people code and vice-versa, but if you always commit small changes, it will be easier to track and fix, so you avoid a lot of time-wasting by tracking down dozens or hundreds of lines changed in a single commit.
In case you make a small commit in your local repository with a misspelling, or you want to change the message to be more descriptive, how can you fix it ? Is pretty easy:
git commit -m “correct message” --amend
Be aware, if previously you already push to a remote repository, better don’t use this.
You can see more about on: Official Documentation
Do you already get yourself in this situation? Where after doing a commit for a new feature, you realize that you need a small change, so you make some little changes and commit again, and end with like 5 commits for the same thing. This looks ugly on your git history, and now you want to fix, no problem:
git reset HEAD~3
HEAD~3 say back 3 commits from head, including the commit on head, with this example yours last 3 commits will be erased from the log, but yours changes on code will remain there, take a look in which code needs to be committed now:
git stage --diff
You will see all changes of the commits that you erase from history are now on stage, so all they can be committed again, this time in a single shot.
Note that HEAD, usually refer to the last commit you did, if you are not sure, check with git log. If your last commit is a merge (uncommon situation), in this case, using HEAD~1 will erase all commits from the merged branch, too see more take a look over documentation.
Be careful this will overwrite all changes, without rollback, usually used when you try something and it didn’t go like you expect. I recommend testing it on a toy repository first.
git reset –-hard HEAD~1
Now your last commit is deleted, as well all changes made in the code there.
The most efficient way to clean the commit history is using rebase, be careful here, because you can delete a commit by miss typing. So, let’s initialize the rebase, in interactive mode (-i flag):
git rebase -i HEAD~5
Once you are in, you will see the last 5 commits (
HEAD~5
) listed inside the terminal, sorted with the newest on the top (This list is open with Vim*), and you have a mini manual with some commands you can use, in most cases what we want is squash and reword.Replacing pick by squash, this commit will be erased from the log, and the code changes will be grouped with the last commit with pick.
If you want to change the message, you can replace pick by reword and change the message direct.
Now you can proceed to another screen, where you write a single commit message for the group of commits that you make squash. To go press ESC and type:
:wq!
Colon (
:
) is to say you want to pass a command, (w
) is to write (save) the changes, (q
) for quit, and (!
) to exec.Note each group will have your message. You can check the result on git log.
*Vim is a default text editor that comes with git, and allows you to edit text files inside the terminal.
If for some reason, you leave this screen with the operation unfinished, you can go back anytime with:
git rebase --edit
If you want to leave without changes, press ESC key and type on keyboard:
:q!
It will say to Vim, to exit without save.
Our commits should usually be either on a single file, or a group of related files. But how can we make quick changes on stage, to make or commits?
Let’s say you have 3 files, and only 2 should be commit, you can make this:
git add .
So remove the one you don’t want from stage:
git reset -- Readme.txt
And check the result:
git status
Add all files from some extension, example CSS:
git add *.css
Added all by mistake? So clean the stage:
git reset --
For more elaborate operations, you can add the files to stage with interactive mode:
git add -i
First choice an option, by typing the correspondent number, like (3) to revert.
After choosing an option you can pass the index of the files that you want to remove from stage, one by one.
When you finish type (Enter).
To add files, same process but using option (4) add untracked file.
To exit, type (
q
) on the options menu.The main point to keep in mind is before pushing to a remote repository and especially before merging your branch, we must make sure our commit history is clean. Once we push to a remote repository rarely someone will fix that.
Want to learn more about pair programming and become a remote software developer? Take a look at Microverse.org
If you have any question, suggestions or want to share your thoughts about it, put in the comments below, I will reply as soon as possible.