Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> I prefer USEABLE history than trashy commits.

Yeah the other day I got into an extended debate about rebasing with another dev who just didn't get this. He maintained that it should not be possible to modify history because it all may be relevant later. I rebutted with a question: do you want a commit every time you type a character in your text editor? Version control is just another tool for code craftsmanship. You should strive to make your commits as atomic and well-described as humanly possible. git-add -i and git-rebase -i are tools that allow you to approach a more perfect history.



> I rebutted with a question: do you want a commit every time you type a character in your text editor?

I don't get it. I want a commit every time I say I want a commit, not upon arbitrary criteria the software decides for me. And I want that commit to be irrevocably and permanently immutable, because I said I wanted it and because it might be relevant later. What am I missing?


When you want a commit, you tell git to commit and it will commit.

When you don't want to revoke or mutate a commit ("irrevocably and permanently immutable"), you don't tell git to revoke or mutate the commit and it won't revoke or mutate the commit.

When you fucked up history and you want to change it, there are some simple git commands to do this and some very, very tedious svnadmin commands to do this.

Some of us fuck up history and want to change it. Some of us don't. Git serves both of us well. Subversion only serves one of us well. A lot of the time we have to use the same version control system, because we want to collaborate.


Additionally, if I have admin access to the SVN repository and rewrite history, how would you ever find out unless I told you about it?

In that sense Git has stronger support for immutable commits, since rewriting published history will actually cause everyone downstream to stand up and notice.


The thing most people seem to miss is that you can't actually mutate a commit in git. You can only appear to do so by removing the old commit and replacing it, and all of its children if it has any, with new commits.

If someone depends on your "mutated" commit, they will notice that it's gone, and you can deal with the issue.

The most common use for rebasing and commit editing is to make commits actually sensible.

Huge end-of-the-day commit-all-my-work chunks do not benefit anyone. The index and rebasing allow you to create commits that make sense, regardless of the state of the working tree. In subversion, this is a painful, dangerous and error-prone operation that involves manually using diff and patch. Git frees the developer from having to worry about when to commit.


smsm42 already said it, and you say you're still missing something, so I'll try another try another way.

If I want to work on some code locally, I might want to experiment and break things, and in the process of doing so I want the ability to commit and have the safety net of version control. That said, a lot of those experiments might be garbage, and I don't want to send garbage to my co-workers when I make a pull request.

So instead, I splash about in my local repo and make tons of commits and screw around with my experiments until they're fully baked, and have tests, and comments and docs and so on. Then I can use rebase to clean up that mess and present them with something atomic and contained that makes clear what I really wanted to publish. The garbage can be tossed from the history or it can be kept around locally, but at least I'm not asking my colleague to trudge through my own thought and work-process.

Does that not sound like a worthwhile feature? If it doesn't that's pretty cool too, you don't have to use rebase at all. Feel free not to, Git works fine without it.


Git's commits are immutable (their identity is an hash signature of their content, they can't be changed), what you want are non-removable commits, ie forbidding the user from moving refs to a commit that isn't a descendant of the current commit.

In practice this is what happens when you share your commits with the world (through push or someone pulling from you). As long as some commits are only in one computer git lets you happily nuke them, but why should it be otherwise? No one can force you to publish your commits anyway, you can always make a new clone and rewrite history there...


Actually you can make something more or less like that by signing a tag, and, as you pointed out, releasing it. this makes it convenient to check that no previous commit as been removed, as git signs a hash of the tag which is a hash of all the hashs in the history

(the tag can still be deleted, but just to show the convenience added)


I don't want anything my computer ever does to be irrevocable. If you want to always commit one at a time and never change them, that's fine - you can just never rewrite your history. But for many people rewriting history is useful, because it's easier to see what the correct commit boundaries in your change are after you've done the whole thing. That git allows these people to do that can't possibly be a disadvantage to using git.


Right, so the greater point I was getting at is that committing is something under the programmer's control. It's not "sacred history", it's all created by programmers as part of their craft, saying you shouldn't rewrite history because you might need it is not much different from saying you should commit every keystroke—they both mean you are of the opinion that you need to know every transformation to the code that happened.


Exactly right. I commit very often when I develop something, and I can have typo commits, test fix commits, really fix it now commits, etc. But nobody really wants to see that when code goes into main project branch - my fellow developers want to see one clean commit that says "fix bug #1234" or "introduce FooBar functionality" and don't care about seeing the tiny details of my process. Rewriting history works wonderful for that.


Alternatively, could you do your trashing about in a development branch and then once you're done make one merge into your main branch? That way looking at the history of your main branch, you'll only see the clean commit merged in, but if people wanted to, they could look at your development branch as well to see how that clean commit came about. If they don't care, they can just ignore that branch.


It doesn't really work like that because a branch does not have a clear, canonical start point in gits history; every branches history goes all the way back to the initial repo commit. You can do some fooling around with diffing the merge parents to try and get some idea of the changes, but it's going to show all the differences (what changes are on master but not on the branch).

Having a single atomic commit to "add feature x" is a lots cleaner when you're git blame'ing then git show'ing the commit, as you get to see the whole picture, instead of a log message like "fixing typo" and a 1 character diff.

That said, this should definitely be done off on a branch, and there's no reason not to have multiple useful commits on a branch merged in as such, but trashy typo/forgot to add X style commits are completely worthless to someone looking back at history


What if when you git merge a branch into master, it collapses all the branch commits into a single commit that appears on the master branch, but the branch commits can still be viewed as being contained within the merge commit?

Meaning you could expand a the merge, see the branches that were merged into the branch, and the individual commits made on that branch.


In a hypothetical DVCS where that was possible, I think it'd be fine.


You can do that (there are options to git merge that will let you squash the merge into a single commit), but IME that's too coarse. I usually want what I've done on a branch to be several distinct commits, just not the hundreds of false starts and minor syntax changes you'd see if you looked at my "real" commits.


The histories actually get merged in when you do a merge between branches. However, it's possible to squash your commits before doing a merge to achieve this effect.


Right, that's what I mean by rewriting history.


I very much want a commit every time I type a character. There is no good reason that undo and version control should be separate things. Of course you want a way to group a bunch of commits into a larger commit and name that, but you want that anyway.


Ah the old TextMate undo debate. Personally I prefer the vim model, but of course that requires modality.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: