Subject: Re: Question about 'branch -d' safety

From: Jakub Narebski <[email-masked]>
Date: Mon, 19 Jul 2010 13:01:20 +0200

On Mon, 19 Jul 2010, Will Palmer wrote:
> On Mon, 2010-07-19 at 01:19 +0200, Jakub Narebski wrote:
> > On Sun, 18 Jul 2010, Will Palmer wrote:
> > > On Sun, 2010-07-18 at 13:55 +0200, Jakub Narebski wrote:

> > > having any kind of suffix like refs~/heads~/bar is just asking for
> > > someone to delete a branch twice.
> > 
> > I don't understand what you wanted to say here.  Using the
> > 
> >   $GIT_DIR/logs/refs~/heads~/bar
> > 
> > (and not $GIT_DIR/refs~/heads~/bar) as a reflog for a deleted branch
> > 'bar' is an implementation detail.  You wouldn't see refs~/heads~/bar
> > when listing branches... well, perhaps 'git branch --list-deleted'
> > could be used to list deleted branches (by scanning for reflogs).
> 
> git branch -d integration
> # git renames logs/refs/heads/integration to logs/refs~/heads~/integration
  # git adds deletion event to logs/refs~/heads~/integration reflog
    (similar to putting creation or rename event in reflog)
> git co -b integration sometopic
> # git creates refs/heads/integration, unrelated to the old one
> (do some work)
> (merge into the main branch)
> git branch -d integration

You touch interesting and important issue.

> 
> Now what?
> git renames refs/heads/integration to ... what?
> - does the old refs~/heads~/integration get clobbered? If that's ever
>   okay, why are we even having this discussion?

That's one solution.  We give some safety net, but not too much of
safety net.

> - does the "old reflog" stuff get combined? If that's ever okay, why
>   even have an extra reflog, instead of just using the reflog we
>   already have?

That's another solution.  We have deletion events in reflog to find
events for first 'integration', and distinguish them from events for
second (unrelated) 'integration' branch.

We can't just deal with reflogs of deleted branches by leaving them
as they are, not moved to logs/refs~/heads~/..., and combining them
because of possibility of D/F conflict (and yet another issue,
described below).  The reflog for branch 'foo' would block creating
reflog for branch 'foo/bar'.  Besides I think it's O.K. to require
more work to access reflogs for deleted branches, but not good to
force more work for reflogs for normal branches.

There is also a variant of the situation you described that makes
it harder for the 'concatenate reflogs of deleted branches' solution
to work well, namely:

 $ git branch -d foo
 $ git branch -m bar foo   
 $ git branch -d foo

where branch 'bar', renamed to 'foo' and then deleted has reflog from
before deletion of first 'foo' branch.

> - do we move everything else one step down, so refs~/heads~/integration
>   becomes refs~2/heads~2/integration? (ie: 2-dimensional reflog, which
>   sounds rather too fancy, to me)

This is yet another solution, although I think the better naming would
be to borrow concept of numbered backups, i.e. have

  logs/refs~/heads~/integration~1~
  logs/refs~/heads~/integration~2~
  ...

BTW., we can even make git branch ask (prompt for answer) whether to
delete old reflog of first 'integration' branch, or keep it in some
form... unless confiogured to always choose one solution.

Sigh... this makes eventual solution complicated, but the problem is
also complicated...

P.S. Wouldn't 'refs~' and 'foo~1~' filenames/pathnames be a problem
on MS Windows / on MS Windows filesystems: NTFS or FAT28^W FAT32?
Or on HFS+ on MacOS X?

-- 
Jakub Narebski
Poland