Photo by William Iven on Unsplash
Frequent.
Descriptive.
Atomic.
Decentralized.
Immutable.
I'll leave it up to your imagination to come up with a clever mnemonic to remember that acronym above.
I love writing about Git and SCM in general because I believe it's crucial to proper CI/CD practices. It's how we submit our code. It should matter.
I've come up with a solid metric for measuring the success and value of a commit. It has 5 key points I've mentioned above.
Frequent
When did you last commit? 2 seconds ago or 2 hours ago. The longer you wait, the more trouble you will have with having your commits tell a story. How long did you wait before your last commit?
Descriptive
Click. That's usually the sound a camera makes when it takes a picture. That's the same idea when Git captures a diff of your changes and you put your label on it. I've found Git commit messages are oftentimes more useful than code comments. Can you describe your change verbosely, yet concisely?
Atomic
Are you the type that throws everything in a laundry bin or do you sort your clothes before washing? We can relate laundry to commit messages, in a way. Your commit should only have related changes. Each commit should be easy to revert. Keep your commits small and relevant and you will never have to undo hours of work. Did you keep this commit small and only containing relevant changes, not ALL changes?
Decentralized
This one is super easy. Git doesn't automatically upload your commits to the "Cloud". Everything is local until you push your commits to a separate repo. Most of us humans use GitHub or something like it. Have you pushed this commit yet?
Immutable
A commit is a commitment. Once it's done, do your best to avoid changing it. That means timestamps, authors, and even the contents should never change after it's saved. Is your commit a "forever commit"?
Top comments (27)
To put it concisely: no.
Or, to be more verbose:
😉
Very true. I'm not a fan of squashing commits because you lose the history (in a way) of each commit message. One of the tools I use in troubleshooting or continuous development is relying on the commit messages of other developers from a quick
git blame
on a file I'm working on. 9/10 times, the commit message is much more useful than a code comment.I agree 100%, but if squashed there is not too much use of blame no?
Color me envious. I wish we used Git at work on my project. Frequent, small check-ins would jibe with how I work. As well as frequent branching.
At work, we use a centralized version control system. Check-ins are large and infrequent, and have to have been compiled and tested before check-in, because each check-in triggers the CI/CD build server. And breaking the build causes other developers to break out the pitchforks and torches.
Compiling the project takes between ten minutes to an hour, depending on how much gets touched. (Although long in the tooth, Lakos's Large-Scale C++ Software Design is highly applicable to my project. Wish we could apply it. Alas.)
Do you have a recommendation for how frequently one should make changes? For instance, I am working on a new feature today, and I plan on committing after I'm done in about three hours. Does that make sense?
Commit frequency depends on the task and your workflow. We use feature branches with git.
When I'm adding a feature to an existing code base or fixing a defect, I usually do a bunch of refactoring commits. I try to keep similar changes together. So I'll get commit messages like:
And then I'll write commits for the new code:
If it gets too big I break it into multiple pull requests. 8-10 commits per pull request is about as high as I'll go.
My main goal is to make my code changes reviewable. Having the refactoring changes separate from manual changes makes code much easier to review.
I also like the idea of using commits like a ratchet. So I'll commit when I'm about to move from a change that I'm sure about to one that I'm tentative about. Then I can revert quickly if I feel I've gone down the wrong path without losing the changes I was sure about.
I start with everytime you hit save. Can you describe your change in one sentence? Commit it. Then after you get into the rigor of committing that frequently, then you can begin to scale back. It's more art than science.
Every time I save? Good lord! I save at least once every 2 minutes.
Lol, but you get my point. It's extreme, but you have to think about the changes you made. Adding classes and methods can constitute a commit.
I think there is one that you missed "format".
A commit should look like this (although the long description isn't always necessary)
Short title saying what commit does
Long description with as many characters as you want explaining why the commit was needed.
This is what I'd meant by descriptive. I'm implying the format of the git commit message.
Writing good commit messages is also crucial.
chris.beams.io/posts/git-commit/
Totally agree. That's why I shortened this article down to just "descriptive". I'm implying the commit message should be descriptive.
I just x-posted my larger article from Medium. Check it out dev.to/sublimegeek/check-out-these...
I certainly don't recommend spending hours on a message. And in your example of the branch names containing the task number, we do that too.
But if branch 2345 is branched off of 1900, then some new commits are added to 1900. By looking at the commit history of 1900, how would you tell when 2345's commits ended and 1900's started?
Date, time, and author may be useful. But that would take more mental power than simply having "2345" at the start of all of 2345's commits and "1900" at the start of all of 1900's commits.
My team's backend branches off of each other quite a bit and sometimes the frontend team does it as well.
So those 2nd-tier branches depend on a 1st tier branch that isn't even completed. So the 1st tier branch could still change as time goes on, from new commits to changing the history of the branch.
That would cause conflicts to occur when the 2nd-tier branch tries to merge into master (after the 1st tier supposedly does) or when it rebases back onto the 1st tier branch.
It all just depends on the team's workflow, the team size, and the complexities of your tasks.
Ideally, nothing would get started that depends on changes that haven't been merged into master.
But in real-life messes happen, and having clear intent and purpose in the commit messages would be beneficial.
If you are spending hours on your commit message, maybe the work was too much for a single commit or you are overthinking the message.
I suppose the second point makes sense if you are creating specialized branches or when you are working locally and before you push your changes you want to show a unified picture in your log.
Thank for this small an concise article about best practices on the commits usage
Had to look that up. For those unfamiliar: git push --force-with-lease