One of them is the "published, shared" kind; for this one, I can agree with you, that they should be self-contained and complete, especially when there many devs on the project, and/or you'd like to be able to use bisect.
The second kind, and for me actually a very important one, is more of a "local backup, dirty hacking" one. Those shouldn't probably be published (unless a private/one-guy repo), but allow for easy hacking, developing, testing, experimenting. The "commit often, whatever you have, however broken or non-ideal" approach provides safe lightweight backup, and allows for easy switching between various paths/approaches. Now, after you design stabilizes, dust settles down, and you are completing the work, you can (and probably should) eventually either just squash everything into one final feature commit (the end result will be indistinguishable to what you'd deliver if not committing in the meantime), or remodel the intermediary commits to whatever ideal shape you like them to have retroactively (with "git rebase -i", including patch editing etc.) Knowing the benefits of this approach, I don't understand why anyone would want to reject it.
edit: Also, with many small, dirty commits, it's sometimes possible to fairly quickly do stuff like carving out some subfeature into a separate branch (with judicious use of rebases, cherrypicking and some occasional small edits). Or, remove/revert commits marked earlier as DEBUG. Seems useful to me, as a means to somewhat speed up such operations and decrease the possibility of manual error at the same time.
If you're using Git or another version control that can do squash/rebase, what would be the advantage of having a separate concept of "temporary commits" or something?
In addition, git has a staging area (git add), which I use to stage intermediate steps of work.
It's a good idea to have only "clean" commits in your master branch (to allow for easy blame/bisect) but you can easily do feature branches that can remain "dirty" before squashing and merging to master.
It'd be nice to be able to mark commits as "squashable" as I went along (without actually squashing them yet), rather than finishing my feature branch and then have to go back and remember which commits were the "good" ones.
With that you can do:
git fixup HEAD~2Other IDEs should offer this feature... it turns out to be quite useful in practice.
http://tewha.net/2012/01/ive-changed-my-mind-about-xcode-sna...
It's always difficult to have these kinds of conversations in the abstract, but for me it's a slightly cumbersome distraction (unless you don't write commit messages). But if it works for you, you should certainly keep doing it. I tend to divide stuff into small chunks so never work on something for long without something that can be committed.
But that, as I said, is most usually. Sometimes, as you considered, I do write just "WIP" or "dump of current state". The second one, mostly when I already don't remember WTF was I doing here... (i.e. when I forgot to commit month ago and left some stuff on the table). The first one... I'm not sure now. But I know I sometimes do; with some guilt too; but usually the need for having that particular stuff committed is stronger than the guilt...
So, still can't really understand why anyone would want to reject it :) but that said, thanks a lot for expressing your approach. As much as it still puzzles me :)
That's what Mercurial phases are:
Is it ever going to help anyone to `git blame` a line of a file and see a commit message like "Whoops, fixed a typo!"? No. But you can't avoid those types of commits.
What you can do is prevent those commits from going into the released history of the product. We develop all new features in feature branches (made _very_ easy with the commandline tool we built for it) and only after code review and acceptance testing do we squash merge it to master.
This lets us put together all of the commits, typo commits, WIP commits and whatever else into a combined commit that contains all of the changes that make up that feature. We even enforce a special syntax on the commit so when you look back in the history, you can trace it back to the code review and to the actual ticket that requested the work.
This means we keep all of our dirty backup commits until release time when we throw them all away in favor of the squashed commit. It makes git blame on any line of any file a sexy experience that provides accountability and an easy way to figure out why the code is the way it is.
Our commandline tool automates a lot of this for us. It's biggest benefit is the tie in with github (and this week bitbucket) to create pull requests and the "deliver" command that handles squash merging and providing the structure for the final commit.
It's all open source and available here: http://github.com/reenhanced/gitreflow/
Do you merge master into feature branches between the time the feature branch is first pushed to the remote and when they are reviewed and ready to merge? Can your command line tool handle creating a squashed commit when master has been merged into the feature branch a few times?
and how would you update a pull request branch to contain the latest master? Merge back and forth?
From the looks of it, this tool is made for the force-push flow, which doesn't suit you. See https://github.com/reenhanced/gitreflow/issues/52
It would be great if we could be perfect, but sometimes small commits to master do have to happen. All we do is make sure we subject every feature to code review and acceptance before it gets to master. If it slips through, then it's technically a new change request in our eyes
Because we don't care about the commits on the feature branches, we prefer doing a regular merge, not a rebase of the feature branch, so that there's no need for force pushing at any point. We consider a force push of any kind to be unnecessarily dangerous.
The tool will handle the merge up for you, but if there are conflicts you'll have to resolve them before you can release the feature.
This allows having "best of both worlds", I think.
EDIT: Take a look at the feature branches on the git flow model: http://nvie.com/posts/a-successful-git-branching-model/
In my experience it is extremely useful to have a bunch of "Unfinished; WIP" commits that I can look through to figure out what I was thinking yesterday when I started writing code. When I'm ready for other people to pull my commits, I'll rebase them into more meaningful commits (or often just one single commit).
My biggest concern here is, that you have to force push because of you rewrite the git history. That way you are most likely going to loose data.
If you need WIP commits to switch branches use the stash instead. You won't overload your history that way in a cleaner way.
Not entirely true. If you only squash when you merge the branch in, there's no need for the force-push.
Rebasing into the already pushed history should be flat out banned without question within teams, and force-push be disabled within configs. It's only in exceptional circumstances where you would actually need to do these.
But why do you need to squash while merging? The concept of merge tells that a branch is merged into the history by adding a merge commit. This commit reflects all differences. It's done automatically if possible - you need to resolve conflicts if it's not.
Correct me if I'm wrong but in my understanding a merge does nothing else than create a commit which is like a squashed representation.
Also, the git reflog keeps references to the pre-squash commits for a time, so the information is still there if you realise you squashed too much.
My recommendation is that commits should be atomic, minimal changes that take the source into a working state. This makes working with git bisect so much easier, but it does sometimes mean reordering and squashing commits.
A safety check in the case where you've got everything working but your history needs some tweaking is to note the hash of your tree in its working state, and verify that the tree you created after squashing has the same hash. You can do that by either inspecting the commit or diffing against the old reference.
If you are concerned about force push then make sure people understand the workflow and/or enforce branch creation policies on your central repo.
That way you don't push all your development commits to the remote and ensure a clean streamlined history.
A problem some teams I worked with have is that there is not one person working on a feature. Especially if you have feature-driven development teams at least 2-3 people actually work on it and a review process is included. That's why teams need to push their feature branches to the remote. Once they are merged: Feel free to delete them. But in my opinion it's hard to work on one feature with several people without distributing the feature branch.
We have a CI server testing every branch for every push - I'd regard it as rather bad to have failing builds 20 times a day.
Worst case could be that it goes live because of some processes related to continuous deployment (misconfiguration happens, in companies of every size) send this to live environments and there is a chance to ruin experience for your users.
when you're all done you clean up the commits with rebase and voilla. life is good.
Then before you push upstream, you rebase down your commits into full feature chunks.
Pushing often is just as import. Computers do fail.
PS: how is a command that demands that you write a commit message really just 'muscle memory'?
;P
(and before the outrage beings, I always push these to my private fork of the main repo, so it's basically just a way of syncing code between machines. Other ways of achieving this with git seem to be always painful; you can push to another machine but only if you rename branches, which is tedious)
- version control
- backup
- syncing
Syncing can, like backup, be had with software and services that are dedicated to that end. I just use Dropbox, though I'm not that worried about privacy. I guess something could be built "from scratch" with rsync, if the ready-made alternatives arent satisfactory?
I backup and/or sync things that I don't have under version control (git). I only sync my grocery list, for example, since I don't need a history of the 'evolution' of my grocery list. Actually, I may have it under a backup scheme, but that is only because of other files and directories in that directory that I need to backup, and I've at this point set (and partly forgot) that backup plan.
My /home/Dropbox contains a lot of files that I regularly need, and it seems a bit excessive to put all of that into one, monolithic git repo.
I guess I could back up every 5 minutes, and I don't think that would be a problem.
So if you want your team to be able to do what you say then someone could force push to master by mistake.
* Getting the stuff off the developer's machine because they didn't push their code.
* Even if the code is retrieved, now the commit log is a mess of commits that were based on nothing but arbitrary time lapses. It would be preferable they're a 'story' of the current development process for the feature and atomic in their own right.
What? Of course it is. Commit as many times as you want, branch when testing out a segment of code, do all the fancy things you need to do - then clean it all up when you're done.
Just because it "works for you" doesn't mean it's sensible or efficient.
There is no downside to having more granular revision history. It's important to recognize that, not necessary to follow, though.
Commit to your branch as often as you want for backups, for milestones, because it's the end of the day, whatever.
The isolated unit of work can be pulled/pushed to the shared stream when it's more complete.
So long as everyone is working on their own branches and pushing/pulling to a shared stream when features are complete, and that pushed to a release stream when releases are to be prepared.... I don't see why folks couldn't comm8t every 5 minutes if they wanted.
It's more interesting to discuss the strategy for moving code from personal branches to development, and dev to release.
If you can push to the shared stream and the others pull it up to their branch, cool. But with interoperability testing of incomplete features that's not ok.
You get the best of two worlds, atomic commits and enough code for your commits to make sense in context.
2. If your commit is too big, you should probably rethink it in smaller steps
Then you should take the time to think about why.
Either you are not understanding the issue or not understanding the current view by most people on the issue.
Either way you're not at industry standard.