News for hackers. Stuff that matters.
Re:SQLAlchemy Migrated from Mercurial to Git by k_bx on Sunday May 26, 2013 @02:32PM (#5771970)
Could someone please explain me an argument about removing branch in git vs closing it in mercurial? As I understand, when you "remove" branch in git, just as when you close it in mercurial, it doesn't delete commits from tree either, since it can lead to disaster (if those commits were pushed already). So someone else could actually start new branch from commit which is in branch you just "deleted". Am I wrong here?
Re:SQLAlchemy Migrated from Mercurial to Git by csense on Sunday May 26, 2013 @09:27PM (#5773037)
> Am I wrong here?

It sounds like you may be a little fuzzy on how Git works.

> when you "remove" branch in git...it doesn't delete commits from tree...since it can lead to disaster

When you delete a branch, only commits and filesystem states that are no longer accessible from any other branch, tag, index, or stash become eligible for garbage collection. So in normal usage [1] [2], you shouldn't ever be able to delete the contents of any commit that exists in the history of any named commit.

A commit that is newly eligible for garbage collection will not actually be garbage collected during a grace period, I believe one week. During this time the commit is still accessible by commit hash [3].

Branches are kind of like variables in a garbage-collected language, and commits are like objects in that language. An object is eligible for GC if and only if there are no variables that point to it. Making new variables that point to the same object is a really lightweight operation since most of the data's shared. Unlike many OO languages, objects in Git are immutable, which means git can safely collapse identical copies of the same object to a single instance (an optimization which git is quite aggressive about).

> it can lead to disaster (if those commits were pushed already)

If you want to cause a remote repository to delete a branch, look at the --mirror and --delete options for the push subcommand. AFAIK, pushing the deletion of a branch has the same effect as if you deleted the branch locally on the machine you're pushing the deletion to.

> someone else could actually start new branch from commit which is in branch you just "deleted"

If another developer has merely fetched the deleted branch, their remote tracking branch will be deleted when they fetch again. If your colleague has created an actual local branch with the changes you deleted (as opposed to a remote-tracking branch), when or whether your colleague deletes that branch is entirely under his/her control [4].

[1] Using low-level git subcommands to force git to delete objects which are still referenced by other objects is abnormal usage.

[2] Corrupting the object database in your .git directory through unclean shutdown, hard drive failure, or vindictive hex editing is also abnormal usage.

[3] If you neglected to write down the commit hash before you deleted the branch, you can likely find it in the reflog. The reflog is a history of the commit hash at the tip of each branch. Alternatively, you can use git subcommands to browse the object database and find orphaned commits.

[4] At this point, git has no technological way [5] for anyone but your colleague to delete the local branch from your colleague's machine. Socially, of course, you can use project management techniques to encourage your colleague to delete the branch (e.g., if the official maintainers announce that the deleted branch is considered obsolete and will not support it or accept changes based on the version of the project in the deleted branch, that can be a compelling reason for people to stop using the copies that are floating around. Or your colleague's boss can tell him to delete it or be fired.)

[5] If you have git push access to your colleague's repository, or you have shell access to your colleague's user account, you can delete their branches. Footnote [4] is referring to the usual case where your colleague's machine is a private box where you have no access.

Re:SQLAlchemy Migrated from Mercurial to Git by k_bx on Tuesday May 28, 2013 @05:13AM (#5779009)
Thanks for your answer. I really was never aware of git's GC mechanisms before, that's why I was sure that commits still hold inside a tree. And you perfectly answered my question (well, at least parts that I understood all details about, I clearly see I'd need to read more some time later).

I still find mercurial's branching model "the right thing" in terms of tree showing development history inside a branch, or overall (multi-branch) history-review (where you clearly see which commit was made in which branch), but I now see that it's really nice from repository-cleanup perspective to have features git has, to deal with non-needed branches and commits (via different mechanisms).

Re:SQLAlchemy Migrated from Mercurial to Git by csense on Tuesday May 28, 2013 @02:33PM (#5781738)
Git's branching model is "the right thing" once you learn the idioms of git development.

For example, if you want to build a new feature, make a local branch so your changes are isolated. You can make work-in-progress commits that split up a large change into pieces, some of which may be experimental, contain debugging statements, or temporarily break things.

Then when you're satisfied your changes are bug-free, you can use an interactive rebase (git rebase -i) to turn the commits into clean patches that would be something you might e.g. send to the mailing list if you're working on the flagship Git project, the Linux kernel.

I like to keep my history clean, six months from now I won't be interested in all the bugs I wrote when I implemented a feature, and all the fixes that I came up with for them during initial testing. I won't want to see the implementation of that feature scattered over multiple commits. I just want to see one clean, bug-free patch that implements the feature.

Re:SQLAlchemy Migrated from Mercurial to Git by 0x0 on Sunday May 26, 2013 @02:49PM (#5772021)
If there are branches with commits that aren't referenced elsewhere, i believe deleting the branch will eventually cause the commits to be "garbage collected". So you can delete abandoned experiments and keep a clean house. On the other hand, commits that are referenced elsewhere (perhaps merged into a main branch) will stay. But you could still delete the branch it was merged from, and avoid having the list of branches grow huge.
Re:SQLAlchemy Migrated from Mercurial to Git by jedbrown on Sunday May 26, 2013 @03:21PM (#5772112)
You can delete commits from Hg using 'strip' (enabled via the 'mq' extension). But this is strict deletion (as opposed to marking it for gc after a grace period) and you can't push an "unreference this commit", so you need admin access on the remote to strip a commit there. If you push branches to bitbucket for review, the abandoned commits stick around as anonymous heads until you strip them via the web interface, but they still stick around for anyone that pulled from you. The Hg community is working on a system [1] for dealing with this, but it's still not ready for general use and I find it significantly more complicated than Git's model.

[1] http://mercurial.selenic.com/wiki/ChangesetEvolution

Re:SQLAlchemy Migrated from Mercurial to Git by reinhardt on Sunday May 26, 2013 @04:25PM (#5772315)
hg strip saves the stripped commits under .hg/strip-backup as a bundle.
Re:SQLAlchemy Migrated from Mercurial to Git by plorkyeran on Sunday May 26, 2013 @04:11PM (#5772268)
> So someone else could actually start new branch from commit which is in branch you just "deleted"

Well yes, of course. They could also start a new branch from any other commit that they happen have in their local repository. Branches aren't really 'things' in git. They're just a pointer to an arbitrary commit that automatically gets updated when you make new commits. It's rarely a useful thing to do, but you don't even have to be on a branch to make commits.

Re:SQLAlchemy Migrated from Mercurial to Git by qu4z-2 on Tuesday May 28, 2013 @01:04AM (#5778186)
A commit isn't really "in" a branch in git in the same way as it is in hg. In hg, each commit "belongs" to a branch (I'm remembering correctly here, right?). In git, a "branch" is basically a variable pointing at a specific commit. A commit can be part of one or many branches (or even none).