Y U NO commit??
github.com
github.com
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.
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.
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/
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.
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.
You get the best of two worlds, atomic commits and enough code for your commits to make sense in context.
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.
2. If your commit is too big, you should probably rethink it in smaller steps
Anyways, this is a cute idea but as someone who compulsive hits save after practically every edit (i.e. after most transitions from insert to normal mode), this wouldn't be very helpful.
> "Set the number of writes without committing before the message is shown"
So after N number of writes to a file, it warns you that you haven't committed.
But I agree, the title of the submission is kind of non-descriptive.
But it in any case, I'm a fan of VCS integration in my editor.
Sometimes I forget to commit, and suddenly I'm in the middle of a second feature, with the code in a non-working state. Then it's perfect to just undo back a couple of hours, save, commit, and redo back to where I am.
However, It's rather risky though if you're not confident with the undo system, so it's a good idea to save the file to a temporary location first.
Or use `git add -p`.
Gerrit topic is here:
https://gerrit.libreoffice.org/#/q/status:open+project:core+...
I'm finding it productive to commit when I have a compilable change. I find it helps me keep track of what's going on.
Happens too often so I setup up this plugin from 20 to 10 and see how it goes! But thanks, the idea is really handy.
and so it goes for literally months, always some feature preventing shipping, always some feature that has to be added.
Beware that trap. Branches are cheap. Use them.
git add <file> -p
This lets you pick chunks of code from <file> that you'd like to stage for commit. When I feel I'm done coding for a session, I just run a `git diff` in one window, and in the other one pick chunks that contain changes that belong in one commit.- if my git repo is dirty (uncommitted changes)
- which branch it is on
- if (and how many) changes I have stashed
It's not originally my work but I find it massively useful, since it avoids the "committed but not pushed" failure mode, the "on wrong branch" failure more and the "stashed and forgotten about" failure mode.
I know that regularly running git status would work, but this is a useful visual reminder for me.
It depends on some git output strings, so is theoretically fragile but in practice has been stable over a few years of git updates.
Alternatively, look into the /etc/bash_completion.d/git file, you can use many funcs in there. Extend it at will.
I thought I'd toss out what my setup is right now on my personal machine, for a bit of reflection/discussion...
- I compulsively save to disk after nearly every edit, so I'm a big fan of editors that provide some kind of persistent undo functionality. Right now I'm using live-archive inside the Atom editor, and it is wonderful. I hit cmd-shift-y and it pops the current buffer open in a live-archive interface that includes VCR-like with rewind/fast-forward buttons, etc. It leaves me feeling quite free to mess with code a little more dangerously that I would otherwise. Whereas before I might briefly comment out a line while I try something out, now I'll just delete it and hack away. Anything that was there is just a cmd-shift-y away.
live-archive is actually maybe the foremost reason I'm still using Atom. I'll probably switch away from it eventually, but I'm grown to like the customized little hole I've built for myself, inside that particular editor. I might try out a JetBrains IDE next, sometime ...
- I don't do a lot of work-in-progress saving. Maybe I should be better about this? I'm not a fan of git histories that read like "went to lunch," "stuck, think on this--" etc. Even when I'm the only one that's going to be seeing them. I keep a gitignored text file where I tend to scribble down notes like this, but maybe I should play around with WIP commits.
- For syncing I have an hourly cron job that does a rsync -av --delete-after for my important directories to several different locations. This is mostly meant as a true sync and not backup, but I do find myself using it as a way to lose no more than an hour's work at a time. I might change this to running every 30 or 20 minutes since it doesn't seem to tax the machine too much.
- For backup I have crashplan backing everything up to a local external drive and then their cloud service too. I haven't put a terrible amount of thought into this. It only runs when I sleep. I want to play around with using arq and amazon glacier eventually.
For git I just do small unit-of-work commits for myself, and then cleaning up when necessary.
A better criterion for determining when to display the message would be to count the non-empty lines of the diff, and only show it if it passes a threshold.
Or: only if the added/removed lines ratio is > 1, or something like that.
I think commiting should be done for a more meaningful unit of work than a single edit, something logically 'complete' akin to a transaction.
> I think commiting should be done for a more meaningful unit of work than a single edit, something logically 'complete' akin to a transaction.
What do you think would be a good set of criteria for what should count as a meaningful unit of work?
I'd consider a meaningful unit of work to be a bug fixed, or feature implemented, at least to the extent that you have a runnable version of the code again (even if you intend to do further work to implement it better e.g. replacing hard-coding). I'd consider changes short of this as not worth commiting, as this would not be a good starting point for further work (I know it's cheap to branch with Git etc., but it just feels untidy to leave something so part-done).
I find that this forces me to take stock of the current state of implementation and put my mind in the right mind frame for the next stage.
When pushing it into the main repository, it will be a unit of work.
If you are exposed to several source control systems, you would avoid GIT, at least until you know what you are doing. But so many people use it and don't understand what they are doing, there are massive numbers of conversations just like this article - often between people who have never used anything other than GIT.