7 ms·
> 1. Local branches Local branches are really an artifact of Git having a garbage collector. That means that any commit that you want to keep must be attached
by rbehrends 12y ago
> 1. Local branches
Local branches are really an artifact of Git having a garbage collector. That means that any commit that you want to keep must be attached to a branch so that it may not be inadvertently lost. Without a garbage collector, that is not necessary.
In particular, in many other VCSs, you just simply commit without having to create a branch in the first place. Labeling them (via whichever mechanisms your VCS provides) is typically optional with modern version control systems.
You can argue that you prefer having a garbage collector over having to explicitly delete commits/branches that you do not want any longer, but that would be a different issue.
> 2. Mercurial, without extensions, doesn't have the git shelf.
This is sort of incorrect -- or rather, probably a misunderstanding. Shelve is part of standard Mercurial and has been for a while (same goes for MQ). While it is disabled by default and enabled in the extensions section, it's no more an extension in any meaningful sense of the word than git stash (which technically calls out to a shell script [1]). Mercurial's shelf is a python module [2] that is loaded when you flip a switch.
> Both these points make hg easier to learn (branch == clone is very easy to wrap your head around, commit behaves basically like svn/cvs).
This is really more a feature of Bazaar, not Mercurial.
[1] https://github.com/git/git/blob/master/git-stash.sh https://github.com/git/git/blob/master/git-stash.sh
[2] http://selenic.com/repo/hg-stable/file/default/hgext/shelve.py http://selenic.com/repo/hg-stable/file/default/hgext/shelve....
- saraid216 12y ago> In particular, in many other VCSs, you just simply commit without having to create a branch in the first place. Labeling them (via whichever mechanisms your VCS provides) is typically optional with modern version control systems. Since, for me, local branches are a massive part of why I prefer git, I'd be interested in examples of how to do the same thing in other VCSs. It doesn't make sense to me that they're a byproduct of having a garbage collector, since (1) git-stash exists, (2) local branches are a common selling point, and (3) git-clean honestly seems tacked on rather than a core piece of the design.
- Blackthorn 12y agoFor Mercurial, you create a new local branch by committing at a point that's not a tip (or not HEAD, if there's just a single branch). By default, it doesn't have a special name (like a git branch does). You can give it a name via "hg bookmark". The feature set is honestly fairly similar, it's just different in the way it is presented. In git you go into a "detached HEAD" and have to explicitly name a branch or commits will get lost. In hg you commit and it creates a new tip, but it doesn't have a name unless you explicitly name it via bookmark.
- josteink 12y ago> In git you go into a "detached HEAD" and have to explicitly name a branch or commits will get lost. Maybe I'm missing something, but this seems like a fairly academical scenario. When would you checkout a specific commit, keep working, keep committing, but not attach it to a name or a branch? How is "67846237864237846" a nicer reference than "bugfix" or whatever? To me this seems like people using git in a way it's specifically designed not to support and then go complaining when things go wrong.
- imakesnowflakes 12y ago>When would you checkout a specific commit, keep working, keep committing, but not attach it to a name or a branch? How is "67846237864237846" a nicer reference than "bugfix" or whatever? You enter a commit message when you make a commit, right? So I am not sure I see your point..
- josteink 12y agoI don't think you understand my dilemma. Let me try to clear it up with an example. Let's say you have the following history: - Commit 1 -> Commit 2 -> Commit 3 (master/default) - current branch Now Commit 3 is the HEAD of your current branch (master, trunk, default, whatever). The way I understand your "problem" is if you want to create a new branch based on an older, non-HEAD commit. For instance you checkout the current branch on based on the state of the branch as per "Commit 2", and make a new Commit "Commit 4". This creates a new implicit branch: - Commit 1 -> Commit 2 +-> Commit 3 (master/default) +-> Commit 4 (implicit branch) - new current branch Now you have two branches. How do you switch between them? How do you operate on those branches? Do you cycle them? Do you have to remember the last commit-message of a branch to find it again? To be absolutely clear: What I'm curious about is how do you relate to and navigate between branches when they are all anonymous? What mechanisms do you have to aid identification?
- rbehrends 12y ago> Since, for me, local branches are a massive part of why I prefer git, I'd be interested in examples of how to do the same thing in other VCSs. You simply commit a new changeset based on the desired parent. The branch would be created implicitly by having a revision with two or more children. It does not have to carry a name; naming revisions (or sets of revisions) is an orthogonal concept for the purpose of navigating the revision DAG [1], whereas in Git branches have the additional purpose of keeping revisions from being GCed. Any revision that is not referenced by a ref (directly or indirectly) will eventually be GCed (once it is removed from the reflog and the grace period has expired). > It doesn't make sense to me that they're a byproduct of having a garbage collector It is a byproduct. Because if you did the above in Git (which Git won't let you without being explicit about it, but it's possible), then one or the other child would get GCed sooner or later. That's because there's only one HEAD commit, and that can prevent only one child from being GCed, so you have to create a ref to the other (generally via a branch) to keep it alive. > since (1) git-stash exists [...] and (3) git-clean honestly seems tacked on rather than a core piece of the design. This has nothing to do with git stash or git clean. I'm talking about one of Git's architectural principles, where the repository is essentially a purely [2] functional data structure and revisions that are not reachable from one of the roots (refs/branches) are subject to garbage collection. [1] And if you look (aside from Mercurial) at Bazaar, Fossil, Monotone, or Veracity, you'll find that there are multiple ways to go about that. [2] Well, not entirely pure, but close enough.
- imakesnowflakes 12y ago>whereas in Git branches have the additional purpose of keeping revisions from being GCed.. Not only that, but it is also used to decide what all commits to show to the user. In that way branch names act as little windows through which you can look at the DAG of history. Commits that you cannot see through this window does not really belong in the history according to git, and will be GC'ed. So if you make a commit on top of a revision that is not a branch head, then it becomes a DETACHED HEAD. Actually there is nothing 'detached' about it. It is linked to the parent commit just fine. But git just does not consider it part of the history unless you give it a name. Here you can see the problem with git naming. 'DETACHED HEAD'. If you understand a head revision as a last revision in a sequence of connected commits, how can there be a 'DETACHED HEAD' when a 'HEAD', by definition is part of a sequence of commits.. I wonder why someone would call it a 'DETACHED HEAD' instead of something like 'UNNAMED HEAD' or 'ANONYMOUS HEAD'....