30

This question already has an answer here:

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.

marked as duplicate by gnat, durron597, GlenH7, Mason Wheeler, psr Apr 30 '15 at 18:28

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 4
    This doesn't strike me as a duplicate because the other questions are all along the lines of "how often / when should I commit" but this question is explicitly "what should I do when life interferes with my commit schedule?" – Jack Apr 30 '15 at 5:18
  • 2
    You've already listed the pro and con arguments. Now you have to weigh them and decide in favor of the side with the greater weight. But only you can do this, because we don't know what weights you attach to orderliness, peace of mind, collaboration etc. – Kilian Foth Apr 30 '15 at 6:08
  • 2
    What about using stash for incomplete work you most certainly resume in your next session? – tobias_ Apr 30 '15 at 6:16
  • 1
    I'd generally branch in this case and merge when the logical work is done. As I understand it, the "stash" is on my machine. If I sync the branch I have a remote backup. – Russell at ISC Apr 30 '15 at 13:39
  • Possible duplicate of Is it ever OK to commit non-working code? See my answer based on a vision of usage expressed by Linus Torvalds as a goal when he created git. – WarrenT Apr 30 '15 at 17:22
40

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.

  • 3
    If you have changes that you do not want to push without rebasing/amending them, you can start your commit message with "WIP" (git -m "WIP: dirty test code"), and activate the pre-push hook under .git/hooks/pre-push. Then git will refuse to push as long as the commit exists. – sleske Apr 30 '15 at 9:35
  • If the task is too big to be finished in the time slot you have, you can make a new branch and do all the dirty stuff there, merging it after all is completed. Sounds good to me. – mattecapu Apr 30 '15 at 13:43
  • 3
    @Bergi Commits should be atomic units of change, and for the benefits of other people who will read the log (which includes future 'you'), it is sometime better to edit intermediate commits, with an interactive rebase, for example. I am not saying every push should be one big commit; on the contrary, it is easier to have a chain of (as small as possible) commits that have a clear purpose. – coredump Apr 30 '15 at 14:16
  • 1
    @Krystian This does not matter, since everything you do on your own local copy is, well, local (I assume you don't share your computer with someone else). You could even commit on master, as long as you don't push in-progress work. That's how I work with git-svn, for example (I also use local branches). – coredump Apr 30 '15 at 14:57
  • 1
    I think this answer should add a little more detail about amending commits. It's the right solution, and you mention it, but I think it's not prominent enough so people who don't already know about amending aren't noticing it. – Brendan Long Apr 30 '15 at 15:41
12

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.

  • 3
    I personally feel like this is the most natural workflow so far. Call me crazy, though, but I just hate rewriting history (squashing commits). Feels wrong, in a sense. – Thomas Stringer Apr 30 '15 at 15:19
  • You're only re-writing history on your personal branch, not the overall projects. Yes some still have issues with this approach, but it allows you to keep on moving forward. I find this approach to very natural as well. Just keeps everything happy. New comers will usually have the problem of having very large commits. Everything still needs to be atomic where each merge back into the development tree is one fix. Keeping this in mind, rewriting history (on your personal branch) is sometimes the only way to keep your own development moving forward. – g19fanatic Apr 30 '15 at 17:05
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.

  • Why take the risk to redo anything? I don't think it is reasonable to advise against committing, especially with git. – coredump Apr 30 '15 at 9:00
  • 1
    @LowFlyingPelican What about committing to separate branches? – jmn Apr 30 '15 at 9:50
  • 1
    a lot of branches that should get cleaned up after they are merged into develop or master... – g19fanatic Apr 30 '15 at 13:46
  • 1
    @LowFlyingPelican The third kind of failure is human error. More often that I would like to admit, I managed to delete files or revert uncommitted local changes. I don't recommand pushing upstream either. – coredump Apr 30 '15 at 14:06
  • 2
    I agree... you can always commit to local repo to counter human error, as per branching I think it depends on the changeset, for example if I was halfway through a new web API method, I would not create a branch, but yes... if I started on a new feature I would create branch when I start :) – Low Flying Pelican Apr 30 '15 at 14:24
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...

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.

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: this advice is good for SVN, where a bad commit breaks the project for everyone. In Git you shouldn't concern yourself about poor commits - as long as you don't merge them to master(and friends) they shouldn't cause trouble to anyone. – Idan Arye Apr 30 '15 at 17:00
  • 1
    These policies seem to be reasoned from the perspective of how should a team work together with a repository, what should the team members see, what you want people to push to a repository you may work with. But a person can commit to private repositories, on personal branches, and squash commits before pushing to a shared repo. Best practices in that private realm have different considerations which are left ignored and unmet by policies such as your answer. – WarrenT Apr 30 '15 at 17:01
  • Yes, I admit this is not a git-specific answer. In fact disregarding the tag I tried to give generic advice, but from what I could understand from the OP's "disconnect" statement, he was referring to actually 'merging to trunk' and not to personal repos... Might be wrong. – G.Rassovsky May 1 '15 at 8:30
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.)

  • Renaming files is often a problem for code reviews, so that's a good reason to make not the slightest change beyond what is absolutely needed. – gnasher729 Apr 30 '15 at 14:38
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.

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.

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