Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Git amend on a commit instead of creating multiple commits [closed]

Tags:

git

For my understanding, git commit --amend can be used to modify an incomplete commit to reach an understandable state, fix typos, etc. However, sometimes it might be (wrongly?) used as a silver bullet for keeping the commit history cleaner (similar to squashed merge).

An engineer just postulated that when developing a complex feature locally (on a branch) they use git commit --amend on one and the same commit over and over again until the feature is done. E.g.:

  • 1st commit: Stubs for functions A and B created.
  • 1st amend on 1st commit: Function A implemented.
  • 2nd amend on 1st commit: Function B implemented.
  • 3rd amend on 1st commit: Add a service X.

The reason for that is their attempt to keep the commit history clean and having as less commits as possible).

The depicted amend-focused approach was new to me since I usually trying keeping the development process more transparent by adding one commit for each logically finished state. E.g.:

  • 1st commit: Stubs for functions A and B created.
  • 2nd commit: Function A implemented.
  • 3rd commit: Function B implemented.
  • 4th commit: Add a service X.

For my understanding, having multiple commits might facilitate the review process, contribute to the understandability of a single line changed (even years later) as well as gives the possibility for resetting to an older intermediate state during development (e.g. in the case of a dead end during the development) since it's not getting "overridden" over and over again.

Besides, due to usually disabled git push --force on the upstream, --amend will not longer work once the commits are pushed. Most likely it will also cause issues when working in a team.

Do you think using "amend" for keeping the history clean is a valid approach or can it be considered being an anti-pattern for a given example? Could squashed merge understood as more accurate approach for cleaner history.

like image 323
dim Avatar asked Dec 05 '25 18:12

dim


1 Answers

What git commit --amend really does is very simple. It does not actually change any commit and anyone using it is still making multiple commits. Unfortunately, getting to the point of truly understanding this is a bit complicated. What you are asking, though, is really a different question entirely: When is this a good idea and when is it not a good idea?

The question you intended to ask does not have a hard and fast answer: it's a matter of opinion and thus not really on topic on StackOverflow. Besides this, it's part of an even larger question, that is even fuzzier: What is the appropriate granularity for work in one commit?

We really cannot answer this question either, but we can take a technical approach to answer subsidiary questions that will feed into one's final opinion-based answer. Specifically, we can look at what each commit is, and does for us. This gets us into a bit of Git-specific-ness, although commits in other version control systems are generally pretty similar in terms of effect, at least (even if the underlying mechanisms are very different):

  • A commit represents a snapshot of all of the files that go into making up the system.

  • A commit carries some metadata: who did this, when, and—perhaps most importantly—why. The why part is in the form of a commit message.

  • In Git, the history is commits. Git achieves this by shoving its own Git-specific metadata into the commit along with the user-provided why this commit exists message.

  • Using the history—the commits in the repository, in the case of Git—we can have our computers do several automated things. The two I would specifically call out here are these:

    • Generate logs (for whatever purpose: just to read to remind ourselves of things, or to build change-logs for release notes, or whatever).

    • Automate tests and do bisection to look for bugs.

The above is not necessarily a complete list, but I think it is a pretty good starting point.

Note that to some extent, the last two bullet points argue in opposite directions: the one that generates logs argues for fewer commits, so that the logs are easier to read and digest, giving a better high-level overview. Meanwhile, the bisection idea argues for commits that are as small and granular as possible, so that when we do introduce a bug, the individual commit that first creates the bug is small enough that the problem will be obvious when we read the diff. So we should have as few commits as possible, while having as many commits as possible.1

How to resolve this is, well, a matter of opinion. We can, however, note that the smallest sensible commit is one that stands alone: the software works before the commit, and the software still works after the commit too. If a larger set of changes, to add some feature for instance, can be broken down into two or more smaller changes, and we prefer (by opinion) the "more granular" mode, we should break this commit into more pieces.

In some cases, a small commit might not actually improve the function of the code at all, but still be justified as a small commit simply because it allows the next highly-granular commit to stand alone. That is, we break off a small chunk of infrastructure work and do it and commit, writing a good commit message that explains that this particular change is preparatory. It will enable our future change.

Usually, getting to this point—commits that are this granular—requires extra time and effort: we might write the new feature as a series of half a dozen (or more) messy, invasive, and/or low-quality commits, just to make sure the idea really works and is useful. Then we go back and restructure the pieces into sensible commits. Time pressures may prevent this, but that's an ideal way to break up a large commit into small, sensible pieces.

In the end, though, we must keep in mind the goal of using a version control system in the first place: it is to make our jobs, now and in the future, easier; to make our software more reliable; to make our software more maintainable; to meet quality control goals; and so on. One often-overriding goal from management is time, which can smash all other arguments to bits. Commit granularity has to be chosen with all of this in mind, and not everyone will agree on the correct granularity.


1Using git log's filtering mechanisms, which allow us to view only some of the commits that are the history, we can actually get the best of both worlds here: have highly detailed individual commits and good overviews. This requires discipline that Git itself does not enforce, though.

like image 51
torek Avatar answered Dec 08 '25 07:12

torek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!