1

I would like to discuss with you this way about the best way to work with git.

We are currently developing software with three people. For version management we use git. The main branch is our productive branch. In parallel, everyone works separately in his own feature branch. This branch is regularly pushed and may be rebased. When a feature is finished and should be included in our software, it is rebased again and then merged (fast forward).

Now let's assume that a branch has the task to migrate the project from Springboot 2 to SpringBoot 3. To do this, the parent-Version in our pom must updated and then numerous changes must be made, for example

  • Adaptation to Jakarta
  • make Hibernate adjustments
  • replace deprecated functions ...

For each of these steps I create a commit. So here for example I get 4 commits (adjust parent, jakarta, hibernate, deprecated functions).

This makes sense to me to keep track of the steps. But if I look at the intercommits by themselves, they are not executable.

I could now merge (squash) the corresponding commits before the merge with the main branch, but then I lose my clean subdivision.

Is it a bad practice to merge these individual commits into the main branch or is it ok, since only the entirety is pushed and the last commit restores a runnable state?

I am very much looking forward to your experiences, assessments and feedback.

2
  • It depends on the agreement with your other colleagues. I push non-building commits and simply add a comment like "does not build" if I really need a copy of that code on the server (if windows pesters about restarts, or if the workspace can get corrupted and need a fresh copy etc). Otherwise I just squash at the merge.
    – Ccm
    Commented Oct 4, 2023 at 20:42
  • The problem is what others are to do with your commit. If you end up squashing it into main, it doesn't matter as it is a snapshot of your work. My own personal convention is to write the commit message as "SNAPSHOT: ...." so the intention is clear. You may also want to create a subbranch just for this. Git is like clay in what you can do with it until you push. Commented Oct 5, 2023 at 5:19

2 Answers 2

3

In my experience, what you do on what is considered a "personal branch" doesn't matter and should be done for your convenience.

When doing work, there are sometimes branches that aren't meant to be shared beyond the person or people doing the work on it. I've typically referred to these as "personal branches", since they aren't meant to be checked out by anyone who isn't actively working on the associated work and they could be unstable, which could include having history rewritten. You could push these branches to remote, and there are valid reasons to do so. For example, when I worked in an office, I would make sure all local branches were pushed to remote before commuting home for the day, just in case something happened to my laptop.

Other branches that are shared between developers need to be stable. Any commit or merge should result in something that can be checked out and used. The team may want to have some definitions around what "stable" means. I would expect it to mean at least "builds", meaning there are no compiler warnings in a compiled language. It could also mean "passes all unit tests" or even "passes all tests" or "passes all tests and static analysis" or even "is deployable".

When it comes to merging work into your integration branch (what you call your main branch), you don't need all of the history of your feature branch. I tend to advocate for squashing on merge to the integration branch. Although a clean commit history could be useful during a code review, once the code review is complete, what matters is a singular commit that delivers a unit of work into the integration branch. Whether it took you 1 or 100 commits into your feature branch to get that work done and address any review comments is irrelevant. This makes the history of your integration branch quite easy to follow and easy to revert changes that are problematic.

At the end of the day, though, you should see what works for your team. If your current strategy is working, there may not be a reason to change (yet).

3

I have a preference for separating different types of commit, for example:

  1. Reformatting - the type that an IDE may do with a keypress.
  2. Relocation/Rename refactors - where files or methods are moved around, but the logic itself isn't changed.
  3. Other changes.

There are a few reasons why I like to separate commits in this way:

  • I can quickly check and/or dismiss the first two types of commit, so that I can focus my time on checking the other changes.
  • If I need to rebase/merge branches I have an alternative way to resolve merge conflicts for the first two - I can simply redo the reformat or relocation.

I prefer not to squish my commits onto main if they are nicely separated like this - because I lose the value of having clean commits. I.e. some time later when you have a complex bug and you start to question what you did before - it's helpful to be able to review and confirm that you did in fact do it right.


Back to the original question, with some work it is often possible to create an "alternate" history where each commit compiles and maybe even passes unit tests. There is some value in doing this as you can review the test changes required for each change along the way, to ensure something didn't slip through the cracks. However I don't think there is any practical way to measure if the time invested in cleaning your history is worth the return of (potentially) finding bugs that you wouldn't otherwise find.

Also note that if the beginning and end commits both compile and pass unit tests, it is always possible to squish the entire history and then manually pull out changes that are compilable / unit testable - I would do this on the branch before code review, so that everyone benefits from the improved history - however again there is a question of ROI with respect to the effort.


In summary my advice would be:

  • Make an effort to clean up your history before a code review - it's a lot easier for you being the person that wrote the code, than the poor developer that has to review it.
  • Don't go overboard on cleaning the history - if some intermediate commits are broken it won't hurt (unless you have some process that relies on every commits to build)
  • If history's are nicely structured, I prefer not to squish them to main.
  • There are some developers who's history have no value at all - those should be squished even before code review **.

** - Sorry I have a pet peeve for developers that apply a change and then reverse the change in a later commit - that is all being submitted as part of one code review.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.