DEV Community

0ro
0ro

Posted on • Updated on • Originally published at 0ro.github.io

🚀 One Git Trick for Perfect Commits 🛠️

Are you tired of seeing vague and meaningless commit messages like:

fix: close pull request discussion
fix: fix review discussion
Enter fullscreen mode Exit fullscreen mode

If you're nodding your head in agreement, it might be time to introduce the "git fixup" technique to your team's workflow, or even just adopt it for yourself.

If the concept seems complicated and overwhelming, don't worry – you're about to be pleasantly surprised. Git fixup is actually quite simple, especially if you're already comfortable with making commits. Let's jump right in! 🏊‍♂️

Imagine you've made several commits on your working branch and have submitted a merge or pull request. However, during the code review, issues were identified—whether by your peers or during your own self-review. Instead of creating separate commits to address these problems, you can simply use the git fixup command. Here's how:

  1. Identify the hash of the commit where the problem was found.
  2. Run the command💡:
git commit --fixup=<commit hash you want to fix>
Enter fullscreen mode Exit fullscreen mode

This command will generate a new commit with the original commit's subject, prefixed with fixup!. This additional commit might seem like a slight inconvenience, but even it is already far better than having vague commit messages cluttering your history.

But we're not done yet. The next step is to incorporate the fixup commit into the original commit using the following command:

git rebase --autosquash -i main
Enter fullscreen mode Exit fullscreen mode

Here's what these parameters mean:

  • -i: Interactive mode for the rebase.
  • --autosquash: A special flag that squashes fixup commits into their respective originals.
  • main: The branch from which your current branch originated.

!!! This is a rebasing command, and you should be aware that this command will change your Git History. So, do it only if you know how it works.

After executing this command, a text editor (VIM by default) will appear. Don't worry—there's no need to make changes. Simply close it by typing :q!.

Image description

Congratulations! Your commit history is now clean and organized. You're ready to share your changes with your team. Just use either of these commands to push your changes, depending on your circumstances:

  • if you work on the branch alone: git push --force 💪
  • if you share the branch with someone: git push --force-with-lease 🤝

To summarize:

  1. Copy the hash of the commit you want to fix.
  2. Run git commit --fixup=<commit hash>.
  3. Execute git rebase --autosquash -i main.
  4. Check the open text editor and close it if everything looks good (:q!).
  5. Use git push --force to publish your changes.

Top comments (12)

Collapse
 
bentzy profile image
Yonatan

I'm sorry but I think this is a bit of a misleading advice, especially to juniors, unless you'll add a warning and caveats to the post.

Like others mentioned, I would not recommend this method unless you really know what you're doing and especially not in the scenario mentioned in the post (after someone already reviewed your PR once) because it will completely destroy the git history as the commit hashes change so GitHub can't connect the PR comments to their original location in the code and the PR comments are now "orphans" and confusing.
Instead, I'd personally recommend a fresh commit for fixing issues in a PR and when the time comes to land the PR to the main branch you can squash merge it in so the PR branches are "messy" and include lots of small meaningful commits while the main branch is clean and linear.

I will, however, definitely follow this advice in cases where you found issues with your code before you pushed it to the upstream branch. As a rule of thumb, if you'll need to force push the code I'd try to avoid this method unless you absolutely know what you're doing.

Collapse
 
0ro profile image
0ro

Thank you for sharing your thoughts and concerns. You've raised some important points that should definitely be considered when deciding how to manage your Git workflow, especially for juniors.

The suggestion of using fresh commits and squashing when merging is a sound practice, but it might not be the best fit for every project. Some teams prefer a more streamlined approach to maintain clarity in their commit history.

Ultimately, the decision should be based on a combination of factors, including project requirements, team consensus, and individual familiarity with Git practices. It's valuable to have a range of strategies in your Git toolkit to adapt to different situations.

There is no a silver bullet for each case, and it can lead to long discussion, with my article I wanted to add one more way how handled such cases.

Thank you again. I will consider to add a disclaimer in the article based on your comment

Collapse
 
0ro profile image
0ro

if you have any questions, feel free to ask, I will glad to help you with optimising your workflow

Collapse
 
lewiscowles1986 profile image
Lewis Cowles • Edited

Been using this since 2018 when another dev showed. A good tip is to use git config so autosquash is default behaviour for rebase.

git config --global rebase.autosquash true
Enter fullscreen mode Exit fullscreen mode
Collapse
 
sentinelaeux profile image
sentinelae

This is totally not recommended for many reasons. The main reason is poisoning the git history, losing references to commits, basically creating a new repo on top of an old one, for simply no reason. I'm sure this is not a trick for perfect commits at all. I'm also sure ChatGPT have its finger here.

Collapse
 
0ro profile image
0ro

It's good that you have another opinion about it. I will be glad to see your article, or a more detailed comment about why this approach is not recommended by you, and what the side effects of it are because I need to get more details about your point to start arguing. Have a good day!

Collapse
 
click2install profile image
click2install

The whole point of git is to provide an audit trail of your code churn. Rebase is a special case that shouldn't be used like this. I have no idea why people are preoccupied with maintaining a clean git history, if you make a change document it in your comment and move on.

Collapse
 
joset98 profile image
joset98

On theory will It maintain the same history (the same quantity of commits, although with new hashes )?

Collapse
 
0ro profile image
0ro

yes, absolutely

Collapse
 
joset98 profile image
joset98

Awesome, thank you dude

Collapse
 
sumanthlingappa profile image
Sumanth Lingappa

Doesn’t this change the commit history?
If I want to change the commit message of an older commit, then all the commit history later to the changes commit will be changed. Please correct me.

Collapse
 
0ro profile image
0ro

Thank you for your question. Yeah, you are absolutely right, rebase command changes the commit history, and this is why later you need to push your changes with a --force flag. Technically with rebase --autosquash all of your commits will be just copied and the fixup commit will be squashed into another commit so your git history will only look like the same, but with different ssh-hashes