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

> Vim is moving to git, GCC is moving to git. What's with all the change?

Git does something very well: it has great support for rewriting version histories. It nearly flawlessly supports almost every conceivable scenario of slicing, dicing, mixing and combining.

It also has great support for working at the sub-file granularity. For instance, this morning I moved a fix from an experimental branch to stable. The fix was part of a huge commit, and consisted of just a few "hunks" out of many in one file. It was obvious that the particular fix, though needed by the experimental changes, could be promoted to stable (it was a change of the kind where some code is altered in such a way that it no longer interacts with the experimental changes, and is improved at the same time.) With git I easily rewrote that big commit such that just those specific changes in the specific file were removed from that commit. This was done without touching anything in the working copy not so much as altering any modification timestamp! ("make" didn't even see that anything needed to be rebuilt after the commit rewrite.) In git we can do "keep my working copy as it is, but alter the history behind it, so those alterations then appear as staged, uncommitted changes". Then we can easily migrate the changes somewhere, like turning it into its own commit, perhaps on another branch. After I migrated those changes to master, I then went back to that branch and did a "git rebase". Lo and behold, that branch picked up the changes, and now it looks as if those changes were written on master all along, before the experimental changes were developed.

Programmers need this kind of thing because we are obsessed about making the perfect set of changes. Since the history of a code base is a digital artifact, we want to be able to hack that artifact to perfection too, not just the instantaneous/current view of the code itself.

Git is also like an adventure game in which you solve quests and acquire higher and higher status. This creates allure. The Novice Adventurer cannot understand all the reasons why the Grandmaster Wizards of GCC have switched to Git, but is mystified and fascinated.



Maybe this is a not-so-frequent thing, but I know it's not just me: As I see it, the big advantage of Git over other attempts at DVCS is that its internal model of the world is very simple and just right.

Early on when Git was still new, I read about the different types of objects (files, trees, commit objects) and how they interact, and everything just clicked. It's the correct model for version control, and I like to believe that that's why it's winning.

In fact, all your praise for Git is something that, as far as I see it, flows directly from Git having the correct model for version control.


I don't think git's model is particularly special in any way - if it were, it wouldn't be possible to make (near) transparent proxies to the other DVCS's.

The fundamental concepts in all the DVCS's are almost indistinguishable; they're just packaged slightly differently.

It's tempting to seek a technological explanation for git's dominance; but all the obvious signs point to it simply being first-mover advantage. Where the other DVCS's do have technical advantages, they're rarely very significant for most people.


Funny you should say that, Git's fast-import format was adopted by most DVCSes for easy transfer of commits from a foreign repository. Transparent-ish proxies do exist, like git-remote-hg. Those others have different models for history (Bazaar uses folder-type branches, Hg's branching is also different) but Git's internal model is a common subset.

But Git was not a first mover. That simple model was pioneered by Monotone. Git won because Linus' use case required high performance. DVCS flows from that (no waiting on the network), as does the index, and it just made for a huge difference in user experience.


I'd forgotten about monotone - my focus was on today's choices, and monotone isn't exactly alive nowadays ;-).

git+hg share the same model for history; that's a DAG of commits. Sure, there are differences, but they're rather superficial. One such difference is in how you, as a human, categorize commits in that dag - what git calls a branch isn't what hg calls a branch. But so what?

In day-to-day use I can't imagine that the vast majority of git users would really notice a ifference if they used hg instead; and I suspect the same thing holds for bzr too. There's no meaningful performance difference. But the point is also that reverse is mostly true too - why not choose git it it's good enough?

And then git's real advantage shines through - it's by far the most common, and that lets you cooperate with a large number of other developers simply because lots of people know git. Oh, and github is popular too and git-only. Then there's the fact that bzr seems dead, as does monotone. The advantage is largely social - though if the currect pace of development continues it way well become technical.


Git definitely wasn't a first-mover. Being used by the Linux kernel probably helped, though. (Though the Linux kernel actually used a different DVCS before Git...)


Rewriting public branch history is not generally used by any major project except in extreme circumstances. This reads like an attempt at satire by someone who doesn't understand the actual utility of history rewriting in git, which is generally for extending version control to your development changes (e.g. what is more formally codified in Mercurial as the draft phase).


Re-read the post. At no point did the author claim he rewrote public history. He had a certain changeset in the experimental branch, an assumed private branch. He then broke that changeset into two, merged the ready-for-production code into the stable branch and then rewrote history of the experimental branch so that it sat on top of the updated stable branch. As simple as that.


In fact, I'm one "hop" away from public. Upstream from me is a staging repo, and public is the one upstream from that. The staging repo is needed so I can bounce changes among platforms. Its branches get rewritten regularly.


Which you can do in Mercurial, Bazaar, or Darcs, too. It's not really something Git-specific.


Ive never managed to do this in mercurial. Its always a huge pain point.

Is there some extension that helps?


All history editing in Mercurial needs to be enabled via extensions (so that you don't shoot yourself in the foot by accident). That said, the term extension is a bit of a misnomer in this context, since most "extensions" that are being used for this are parts of core Mercurial and are simply enabled by an option (the one prominent exception I can think of is "evolve", since it's unfinished).

Here's how you do it:

  hg histedit -r .
  # change "pick" to "edit" in the edit plan.
  hg commit -i
  hg commit
  hg histedit --continue
Alternatively, and preferred, because you can then test intermediate commits:

  hg histedit -r .
  hg shelve -i
  # test that it works
  hg commit
  hg unshelve
  hg commit
  hg histedit --continue
If you don't want to affect the files in your current checkout, use hg share to create a separate checkout.

That splits the commit in two; use hg graft or hg rebase to move the commits to different branches.

> Its always a huge pain point.

Not sure why; Mercurial's commands for history editing are conceptually pretty similar to Git's. I suspect that it's mostly a difference in familiarity with the tools.


I'm sure part of it is familiarity, but also a difference in documentation. Git's documentation makes it EXPLICITLY clear that one thing Git is intended to be awesome at is easy branching and merging, and rebasing. When I worked on a Mercurial codebase, we pretty much didn't do feature branches (or the hg equivalent), and therefore "rewrite history" was considered not just heresy, but likely to Break Everything.

It's not that it's impossible, but that it was not clearly described how to do it right, in contrast to the Git documentation. Now that I've been using Git for nearly three years, and have used it to save my bacon, I'm sure I could find some way to do similar with Mercurial ... but only after having learned it with git.


> Ive never managed to do this in mercurial.

`hg record` might be somewhat more cumbersome than `git add -p`. But `hg rebase` should about as nice as `git rebase`?


hg crecord is awesome for fine grained patch splitting.


> Its always a huge pain point.

And that is a nonstarter, once Git has opened your eyes to light-weight rewriting, done casually and frequently.


I think I was Poe's Law'd by his last paragraph


Even public history can be rewritten, and it's not too bad to deal with. For several months, earlier this year, I was battling some tough bugs in a kernel USB driver, along with a few other developers. I set up a "wild repository" (not an official repository, but one for experimental changes---though public in the sense of being shared). I rewrote the testing branch regularly. I even adopted a scheme, whereby I would rename a branch through the names "name.1" and "name.2" (deleting the old name.2), similarly to rotating logs. I'd send out a "heads up" e-mail whenever I did this.

A rewritten branch isn't hard to pick up. Git tells you that the history has diverged (N commits here, M over there). If none of the local history is yours, you can just throw it away with a "git reset --hard <origin>/<branch>". Or else you can rebase those changes which are yours.

It's only bad to rewrite "really public" branches that are distributed to the world. Even then, it can be okay to clean up some oops: like seconds after pushing a release, some last minute change needs to be made (typo in the release notes file or whatever).




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

Search: