2

Best practices with git (or any VCS for that matter) is supposed to be to have each commit do the smallest change possible. But, that doesn't match how I work at all.

For example I recently I needed to add some code that checked if the version of a plugin to my system matched the versions the system supports. If not print a warning that the plugin probably requires a newer version of the system. While writing that code I decided I wanted the warnings to be colorized. I already had code that colorized error message so I edited that code. That code was in the startup module of one entry to the system. The plugin checking code was in another path that didn't use that entry point so I moved the colorization code into a separate module so both entry points could use it. On top of that, in order to test my plugin checking code works I need to go edit UI/UX code to make sure it tells the user "You need to upgrade".

When all is said and done I've edited 10 files, changed dependencies, the 2 entry points are now both dependant on the colorization code, etc etc. Being lazy I'd probably just git add . && git commit -a the whole thing. Spending 10-15 minutes trying to manipulate all those changes into 3 to 6 smaller commits seems frustrating which brings up the question

Are there workflows that work for you or that make this process easier?

I don't think I can some how magically always modify stuff in the perfect order since I don't know that order until after I start modifying and seeing what comes up.

I know I can git add --interactive etc but it seems, at least for me, kind of hard to know what I'm grabbing exactly the correct changes so that each commit is actually going to work. Also, since the changes are sitting in the current directory it doesn't seem like it would be easy to run tests on each commit to make sure it's going to work short of stashing all the changes. And then, if it were to stash and then run the tests, if I missed a few lines or accidentally added a few too many lines I have no idea how I'd easily recover from that. (as in either grab the missing lines from the stash and then put the rest back or take the few extra lines I shouldn't have grabbed and shove them into the stash for the next commit.

Thoughts? Suggestions?

PS: I hope this is an appropriate question. The help says development methodologies and processes

1
  • I'm curious why this was downvoted. As I pointed out according to the help this seems like an appropriate question. If you downvoted it can you please explain why so I know what the supposed rules are that are apparently different from the actual posted rules?
    – gman
    Aug 24, 2014 at 8:37

2 Answers 2

2

The thing to realize is the smallest commits are most beneficial to you, during development. If you wait until you're ready to push to separate out commits, you're missing out on a lot of help your tool could be providing.

What you do is work on recognizing when you're switching gears, and just make a commit or a branch on the spot. That lets your tool help answer questions like "what changed since I started working on the colorizing code?" It lets you more easily back out partial changes when you realize you're taking the wrong approach, which happens most frequently right after you first write something. It also sometimes help keep you from distractedly bouncing around from one task to another. Because you don't want to make a branch, you focus and get the part you're working on to a good place for a commit.

Often people want to clean it up before a push anyway, but the difference now is you already have nice small commits breaking everything up, they just might need some rearranging and consolidation, which is a lot easier than doing the breaking up after the fact.

3
  • I think I need a more concrete example. Taking my example from above. First I start writing the plugin version checking code. Then I decide I want to edit the logging code. So you're saying at that point I should commit the unfinished version checking code (so I have a broken commit). Then I should make new branch from the a version without the plugin checking code and make the logging change. Then I should rebase the unfinished plugin checking code on top the new logging code, and then finish that up. I guess I would find that fairly hard. I can get 6 levels deep sometimes and with cross-deps
    – gman
    Aug 24, 2014 at 2:56
  • 1
    I would create a branch only if absolutely necessary. Just the commit when you switch gears is usually sufficient. The definition of "broken" is different for unpushed commits. If it's passing unit tests with the unimplemented dependencies mocked out, that's fine for a commit, and you shouldn't have a stretch longer than a few minutes where you aren't in that state. Creating the commit will help you recognize when you're going too long with broken code. Aug 24, 2014 at 3:23
  • 1
    Who cares if the commit is broken? You can go back later and fix it. Nobody will ever know. Rewriting history is easy as long as nobody else knows the truth! (IOW: amending commits is fine as long as you haven't pushed them to a public repo … or more precisely, as long as nobody else has pulled them from a public repo.) That's the beauty of DVCS: nobody has to see what actually happened, they only see the history you want them to see … which is that you of course knew all along that you wanted output to be colorized and put in the necessary interfaces from the start ;-) Aug 24, 2014 at 6:56
0

My own general rule is to keep commits as modular as possible. When developing something new, I keep commits relative to sections in the wireframes so they relate to pages/sections. While maintaining a consistent naming convention that others could quickly pick up on.

Regardless of how many files are in a commit at a time, I think an important questions is, do the files in the commit all pertain to the message. I find I commonly have minor, insignificant changes that are part of the commit that aren't totally relevant, but this is bound to happen form time to time. After I've finished major milestones, i habitually create annotated tags with git tag -a NAME_OF_TAG. If you're using something like github, gitlab, or bitbucket, you can download these sections for historical reference.

Commonly I find myself adding files to the repo, at points where I haven't committed files I am already tracking. It's handy to use git add -u, which adds only files you are tracking to the staging area. Once the tracked files are committed, I can move on to adding and committing the newly added files.

Keeping things in order seems to be hardest when you're a) refactoring or b) fixing bugs. At these points I like to make branches which further helps keep me organized, as well as keeping the main line safe.

A useful tool for re-organization, git rebase -i. I've rebased at a time where I needed to change the order of two commits and this was a handy way to alter history in a helpful way. Rebase has much more it is capable of, but thats just one example. Editing commit messages is also possible during an interactive rebase. Rebasing is an option to be aware of, I would rely on this as a "first option".

Your Answer

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

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