23

When working on a fix or a feature, I sometimes stumble over other tiny issues that can be improved on the fly in a matter of seconds. When I do them immediatly and then commit the finished feature/fix, the commit includes more than one thing. For example "add feature X and code clean up" or "fix bug X and improved logging". It would be better to split this into two commits. In case the two changes happened in the same file, I can not simply add one file, commit, add the other and then commit again. So I see the following three options:

  1. Deliberately overlook non-related things while working on something.

  2. Copy the file with two changes, revert it, include one change, commit, include the other change, commit again.

  3. Do not change small unrelated things but add them to a todo list and do them later.

I do not really like all of the three options, because of the following reasons:

  1. Code quality can suffer if one does not fix small problems. And I feel bad if I consciously miss a chance to improve something without much effort.

  2. This increases manual work and is error prone.

  3. This is fine for not-so-tiny todos, but adding a tiny item to a todo list and revisiting it later often takes much longer than just fixing it immediatly.

How do you handle such situations?

  • 7
    Doesn't git allow you to check in individual lines rather than entire files? – Kilian Foth Feb 8 '16 at 14:56
  • Possible duplicate of Can commits be considered too small? – gnat Feb 8 '16 at 15:03
  • I use git add -p a lot which lets me interactively select the parts of the files I want to commit. If the clean up is sufficiently separate, this is easy to do. If separation is more difficult, I commit the state on a temporary branch, then manually add the changes to my actual branch until there's no diff to the temporary branch. This requires a lot more work, but allows me to check that each commit works on its own. – amon Feb 8 '16 at 15:10
  • 1
    @gnat: obviously not a dupe. OP ist not asking about the correct size of a commit - he wants to do small commits. He is just for looking for a more efficient way to do this. – Doc Brown Feb 8 '16 at 15:30
  • 2
    @gnat: top answer says nothing (!) about how to handle different changes in one file and how to split them up into separate commits. – Doc Brown Feb 8 '16 at 15:33
11

I think that you have to be very pragmatic when programming. Even if it might be possible to formulate the perfect scheme, workflow, or implementation, sometimes you just need to get work done. Here's what I do:

I use git's ability to stage/commit individual hunks and lines, whenever possible, to separate unrelated changes, although, occasionally this can introduce temporary problems, if the separation was not done properly. Since the changes will be adjacent, it's usually not a massive problem, unless you have a policy of testing every individual change in your CI pipeline.

When the unrelated change is too large, I will put it on a todo list, and usually take it on right after, while its fresh in my mind. Sometimes it might take a day or two before I can get back to it, it depends on my current task and train of thought. Occasionally I will simply put a TODO: next to the offending code, if I don't have a good solution ready.

It happens that it's just not practical to separate things and I will commit the minor adjustment along with the original work.

The size of the change is usually the determining factor when I pick the route to go, but in the end I would much rather ignore a workflow rule, than leave a smell behind.

7

My editor has a plugin that makes staging individual parts of a file extremely easy. I imagine other programmer editors might have similar plugins, although you can always do it the manual way with git add --patch | -p. Then I use git stash to save off my other changes to test my small commit in isolation. Then after I commit, I just do a git stash pop and continue where I left off. That's precisely what those features were designed for.

2

The trick is not to make changes unless you are prepared to put as much effort in as the change deserves.

What I do tend to do is add to a todo list (sometimes by adding comment to the code, sometimes in a note on a bug ticket, and sometimes by updating the code in a separate branch knowing the fix will get merged in eventually). If there is no bug ticket for a rollup of minor quality issues, I raise one specifically for this, so I and everyone else can tell what the reason for those code changes was when the branch gets merged. I never just make changes for the fun of it, everything gets traceability so my colleagues will not be too surprised when code changes.

So in short - yes, overlook them when coding. If you're adding a feature, do not be tempted to add 2 features, no matter how small. If someone decides to revert your branch (because your feature is no longer required, say) then you will also lose all your mini-bugfixes. Similarly, you do not want to make a small 'fix' in some critical code that was working correctly.

  • 1
    The OP did not suggest to merge two changes into one commit, quite the opposite. – Doc Brown Feb 8 '16 at 15:38
  • 1
    @DocBrown he does suggest mixing 2 changes into a single branch though, that can be messy to unpick later, though obviously not as messy as 2 changes in a single commit. – gbjbaanb Feb 8 '16 at 15:57
  • Ok, I see what you have in mind with your final paragraph. – Doc Brown Feb 8 '16 at 17:22
2

An option I use quite a bit is to add TODO comments, then do lots of frequent "partial" commits, by using git add --patch to select the relevant parts of the file. Then use git rebase --interactive to reorder and merge the partial commits into the final feature and fixup commits before pushing them.

This keeps your main commit clean, and still allows you to fix other issues you find immediately.

There's nothing wrong with a git rebase in this context as you're only rewriting local commits.

1

Another option could be to "git stash" your current changes. The workflow would look like this:

  1. Start making changes related to Feature A
  2. Discover Bug B and decide to fix it immediately
  3. From the command line in your repo perform git stash (After which your code will be back to the state it was in before you started working on Feature A)
  4. At this point your uncommitted changes for Feature A are stored in the "stash"
  5. Make the code changes necessary to fix Bug B and make a commit back into the repo
  6. From the command line run git stash pop
  7. Your uncommitted changes for Feature A are now popped off the stash and restored to your in progress code along side the (already committed) fix for Bug B
  • Could you expand a bit more about how this workflow would work? What is the state of the repository at each point? Could you walk someone through the process of using git stash? – user40980 Mar 6 '16 at 14:17
0

Separately stage (and commit) the changes related to the bug-fix. In Git Extensions, this is extremely easy to do. From the commandline, I think you need to do git add -p.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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