Nicolas Pitre <nico@xxxxxxxxxxx> writes: > On Wed, 21 Oct 2009, E R wrote: > >> What solutions have you come up with to either to catch or prevent >> this from happening? It is possible to determine what node a branch >> started from? > > This can be determined by looking at the gitk output. > > Also 'git merge-base' can give you that node, given the main branch and > the topic branch. See documentation about git-merge-base. > > Then if you need to move a branch to another starting node, then 'git > rebase' is what you need (again the git-rebase documentation is pretty > detailed). That is a correct way to diagnose the mistake and recover from it, but unfortunately it is a rather weak tool to identify the mistake in the first place. A branch in git, as Randal often used to say on #git, is an illusion---it points only at the top and does not identify the bottom. But it does _not_ have to stay that way at the Porcelain level. Here is a rough sketch of one possible solution. It is not fully thought out; the basic idea is probably sound but I did not try to exhaustively cover changes to various tools that are necessary to maintain the invariants this scheme requires. (0) Define a way to identify the bottom of a branch. One way to do this is by an extra ref (e.g. refs/branchpoints/frotz). Then the commits between refs/branchpoints/frotz..refs/heads/frotz identifies the commits on the branch. None of the additional restrictions below applies when the branch does not have such bottom defined (i.e. created by the current git without this extension). (1) At branch creation, the branchpoint is noted. E.g. $ git branch frotz master~4 would internally become $ git update-ref refs/heads/frotz master~4 $ git update-ref refs/branchpoints/frotz master~4 You would also need to cover "checkout -b". (2) You can grow the branch naturally with "commit", "am" and "merge". The bottom of the branch does not have to move with these operations. (3) Operations that alter histories, e.g. "commit --amend", "rebase", "reset", while on a branch that records its bottom need to be taught to pay attention to not break its bottom. Paying attention needs to take different forms depending on the operation; some probably will forbid the operation while others would automatically adjust the bottom. Examples (not exhaustive): (3-a) "branch -f frotz $commit" This moves the tip of the branch. Unless $commit is already some part of the existing frotz branch, we should probably forbid it for simplicity, when a bottom is defined for the branch. We could later loosen the rule so that $commit is only required to be a descendant of existing bottom of the branch to support a workflow like this: $ git checkout -b frotz master~4 ;# records branchpoint $ edit; git add; git commit; ... ;# builds history $ git checkout HEAD^ ;# go back somewhere on frotz $ edit; git add; git commit; ... ;# builds an alternate history $ git show-branch HEAD frotz ;# check progress $ git diff frotz HEAD ;# is this one better? $ git branch -f frotz ;# I prefer this new one better (3-b) "reset $commit" (with or without --hard/--soft/--mixed) This is similar to (3-a) above; $commit has to be a descendant of existing bottom. (3-c) "commit --amend" $ git checkout -b frotz master~4 ;# records branchpoint $ git commit --amend ;# rewrite the bottom??? would probably be a mistake, as the end result would make the frotz branch forked from master~5 with the first commit on the branch a fix-up to what is already in the master branch. However, this is a valid way to work: $ git checkout -b frotz master~4 ;# records branchpoint $ edit; git add; git commit ;# builds history $ git commit --amend ;# fix the tip and it does not have to do anything to the bottom. (3-d) "rebase" $ git checkout -b frotz master~4 ;# records branchpoint $ edit; git add; git commit; ... ;# builds history $ git rebase --onto master ;# transplants the branch would make the "onto" commit the new bottom. Another interesting thing to note is that we do not have to compute which commits to transplant with merge-base with the "onto" commit, because we know the bottom commit of the branch. (4) Operations that browse histories, e.g. "log", "show-branch", while on a branch that records its bottom can be taught to pay attention to the bottom. For example, it is conceivable that $ git log $ git log -- Documentation/ without an explicit branch name that fell back to the default HEAD while on branch "frotz" might be better run with an implicit bottom ^refs/branchpoint/frotz. We probably could kill the other bird in the nearby thread that wants to add a description to a branch, if this scheme is fully implemented (no, I am not going to start coding right away, as this message is just a sketch of what we _could_ do), As we will fully know in what operations we need to update the branchpoint ref, we could make the refs/branchpoints/frotz an annotated tag, and store the description for the branch in that tag. Whenever we need to adjust the branchpoint, we update it while carrying the branch description message over to the new tag object. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html