32

Life, the work day, and personal projects don't always give us the opportunity the commit code at a logical completion (functionality subset programmed, bug fix completely patched, etc.).

Sometimes we need to stop working half way through a new method, or through a half-baked fix. Think... The work day ends, or it is time to shut down for the evening.

I feel guilty in doing a commit at this point. Mostly because my commit message is some daft comment saying "Started to do blah" or "Did this partially but need to complete".

Committing without a nice a logical stop feels sloppy, mostly for commit log and historical purposes.

But at the same time I don't like to "disconnect" from the code or call it quits with an uncommitted working directory. Maybe unfounded, but also for the sense of not having a dvcs backup at this point in case of a hardware failure.

What is the right approach here? When you are at a force programming stopping point but not a logical stopping point in the code, commit or wait until that logical containment is done to commit? Does the latter contradict the "commit often" mantra? It just seems history and diffing this could become difficult to understand after the fact.

Thomas Stringer
  • 2,247
  • 2
  • 18
  • 19

9 Answers9

41

Committing code is cheap in git. You have several options:

Commit and amend later

    $ git commit --all -m "WIP: half-implemented hack"

... time passes ...

    $ # back to work
    $ git commit --all --amend -m "Nice logical atomic commit"

Use git stash

Same as above, but using a stash:

  1. Commands are a little shorter to write
  2. A stash by nature looks like work in progress (stashes are named "WIP on master" by default).

    $ git stash # must go home now
    

    ... later ...

    $ git stash pop # back to work
    

Note that your work will temporarly be reverted, which could be confusing if you forget that you worked on something. It helps to work with gitk or magit (emacs) in order to see stashes.

Commit and rebase

You can split your work in different units and/or experiments. When you are done, do a git rebase --interactive (-i) to edit individual commits (the command expects a base commit as an argument). Then, you can push your changes upstream (or not; it helps to clean regularly).

Why commit?

You should commit, because even though failures are minimal, the cost of committing is so low that you don't have to take a risk. As noted in the comment, at any point you can choose to have a local branch to keep things organized, if it helps.

Basically, anything you do locally is good, as long as you don't push temporary commits.

That being said, you can push your half-worked changes to another server, provided you only do it in a personnal, private branch.

coredump
  • 6,015
13

Commit away. Commit as often as possible. Commit when its incomplete, commit when its finished. It really doesn't matter. I even will commit and push to remote when I get up for a 1 hour meeting or lunch even...

The catch is you need to be in your own branch (one that no one else will be pulling from). This should be a part of your normal development cycle anyways and is the easiest way to keep git history clean. Before your merge into the parent development tree, clean up your history by squashing commits. It takes almost no extra time and really allows you to pick and choose what commits make it into what commits/pushes.

I will often work on several different bugs before squashing commits, rebasing on parent remote branch and merging with parent remote branch. My commit messages tell me when i've finished with one bug and have moved onto another. I will squash down the commits to 'single' commits that contain each 'fix' in one commit and merge them upstream. Commiting often and with good messages when necessary will allow you to not worry about semantics and get a move on with coding.

6

The concept of committing the code when it reached a 'milestone' is mostly due to, other developers/testers should be able to checkout the latest version without fearing that they can't compile / debug the code because it's broken.

When it comes to the distributed version control systems like Git, there is no such issue when checking in the code as it's committed to the local repo, but pushing that matters.

When you have a half baked code and when you have to stop work, I believe it would be fine to stop where it is and resume next day rather than committing, because the risk of hardware/software failure is minimal. Also it's important that the changes are reasonably small changes that even if you lose the change due to hardware/software failure, you should be able to redo it without a lot of effort.

6

I say that not only you may commit unfinished changes when you need to stop working on it - you probably should do it. When you have to leave a task for a long time, always assume that you are going to "context-switch" by the time you're back. Now, if you are just going to make a coffee - or even take a launch break - you should be fine, but if you leave the office or switch to another task by the time you went back to the original task you'll have to make an effort to recall where exactly you have stopped.

This is where committing can help you - commit everything, write in the head "Temp" or "WIP" or whatever to indicate that it's not a fully baked commit, and write in the body notes to yourself regarding what were you doing, what were you planning to do next, what are the current unresolved problems you are encountering - whatever you think you'll need to quickly get back to that task.

Source control is not just for not losing your code - it's also for not losing track of your code.

Of course - never push these commits to one of the main shared branches(master, develop, release-### - whatever branches used by all developers). But if it's a private branch - go crazy. You can always force-push to it - you are the only one working on it.

And don't forget to amend these commits once you are done - you don't want all these temporary WIP commits laying in your graph...

Idan Arye
  • 12,145
4

A local commit can always be safely amended if it hasn't yet been pushed upstream, so you could commit at the end of the day and take it up again the next. However, this is of limited utility as far as code sharing and redundancy are concerned, unless working on a branch that's yours alone. In that case, you've got the right to push one day and force an update the next, which leaves anyone else who's pulled your branch responsible for dealing with the aftermath. Notably, this sacrifices a certain amount of automated revision management and leaves it up to the people involved.

As git is flexible enough to support various workflows, what commit & share schedule to use ultimately depends on your team's needs, so they can provide the exact answers you seek. It sounds like, at the very least, a local EOD commit will meet your individual need to keep changes organized in commits.

outis
  • 1,171
4

Your question really depends on quite a few things: Code Base complexity, change complexity, people working on code base, people affected by your change, etc.

I personally avoid committing unfinished business, even if that means not committing for a few days (Many people will disagree here). And it certainly is good to stay "connected".

So in light of all that, I would say: If the task is too big to be accomplished before the end of the working day, then maybe the problem could be split into smaller problems, thus tasks, and each of these can be committed separately in a non-destructive manner.

Here are some other points which I like to remind myself when committing (they are just guidelines and do not apply everytime):

  • Commit working code - even if you have to make several separate commits (large code base, multiple working copies, etc) make sure you commit in such an order, which will not break the codebase, if someone was to update halfway through your commits.

  • Committing should NOT be the last thing you do - Avoid committing at the end of the day, without checking/testing/running/whatever. This, more often then not is a bad decision. You are tired, your mind is focused on what you are working on and doesn't always see the big picture... especially bad when working with other people, who will be affected by the change... Better commit in the morning, yesterdays work.

  • If you have multiple logical changes in a single file, commit them separately (when possible). You don't want to confuse people when they look back through your commits, especially when it is a complex one, involving many files, etc.

  • Break the big problem into smaller problems - It is far better and clearer to have a few smaller commits with an encapsulated logic and a concise commit message (perhaps even linking to other related commits), than one huge commit with a message resembling an article.

  • Avoid committing commented-out code, avoid commenting out code and committing - that is why you use version control in the first place... If something is so far from being finished, that you need to comment it out, so that the project can build - DON'T commit it... If something needs to be removed from the code base, DON'T comment it out, but remove it.

1

From what I've observed, different people vary greatly in their commit frequency. Some people make frequent tiny commits, and others make rare big commits. I've seen people not commit until they finished several weeks of work, resulting in one gigantic commit that touches hundreds of files.

IMHO, huge commits are a bad idea. I like to think of commits as kind-of atomic units of work. I tend to make frequent small commits.

For example, if I rename a file, that probably means the filename has to change, the project file has to be updated to point to the new path, the name of the code inside the file probably changes, and therefore any code that refers to this must also change. That's quite a lot of changes, but conceptually I've only done one thing: rename this file. So I would make all of that stuff into one commit. So that anybody looking at the history can see that all thus stuff happened, but semantically it's just one trivial operation.

I often go to the point of changing a whole bunch of stuff, and once it compiles, actually going through the commit GUI and picking the changes apart into conceptually separate sets. So if the code wasn't quite working, and I try a bunch of stuff, and it turns out there were three unrelated problems that were stopping it working, I'll make that into three separate commits.

It's best if you can commit stuff at points where the code still works. But I don't always hold rigidly with that. Perhaps changing this interface and the code that uses it also breaks 3,000 unit tests. In that case, I probably commit the related changes to the code, and fix the unit tests in a later commit.

Another thing worth keeping in mind: Committing stuff isn't just about "saving your work". It's also a "safe point" to come back to if you end up screwing the code up so badly that it doesn't seem to work anymore, and you just want to revert it all to the last working point. If you have 6 weeks of uncommitted changes (!!) then this is very, very awkward to do. For this reason if nothing else, commit often. (But try to keep it as units that can have a meaningful commit message.)

1

It all depends on the meaning of "check in".

With git, you can have a private repository, so checking in is nothing more than a personal backup. I make a small change, it works so far, I check it in. I do some experiment, it doesn't work, or the experiment tells me what I want to know, I cancel the checkout. That means I have to check in when there are things I don't want to lose.

Then comes the point where you check in changes to a shared repository. If your code doesn't compile, they will be very, very annoyed. It's Ok if you have changes that compile but are incomplete, as long as they don't affect anyone (for example, you can have a half finished feature that needs a switch to turn it on, and you check it in switched off). But this depends very much on company rules. And the company rules depend on how you people work.

gnasher729
  • 49,096
1

Something to consider, are you using distributed version control or centralized? (Edit: I realize this was tagged as git, but I still feel there's relevant information about deciding when to commit in my post.) If it's on your local machine or your own personal branch then do what feel right, but I'd still lean towards to following below.

At my job we use SVN, because my commits could end up in a build I don't like to check things in unless they are mostly done. The whole story/feature doesn't need to be implemented, but I like to at least have logical subtasks complete, things like

  • Makes schema change for new product
  • Adds ui element for new product
  • Adds processing for product

as opposed to

  • Started ui changes for product
  • Partially implemented new processing for product

To me, if I can't phrase my commits in a way like "Adds x", "Removes x", "fixes x" then I take it as a red flag. Each commit should be clear about how much it does.

I'm new to professional development, so this might all be phrased poorly, sorry. Really it comes down to two questions,

  1. How "public" is the commit?
    • local vs. shared?
    • is it to some master branch or a personal branch?
    • is it likely to end up in a build?
    • is it likely to end up in a build handed to QA?
  2. How fleshed out is the feature?
    • completely done and tested?
    • completely done but untested?
    • mostly done?
    • likely to break other components?

The stronger your answer to question 1 the stronger your response to question 2 needs to be to check in.