Git shouldn't allow to push a new branch called HEAD

6 messages, 5 authors, 2016-06-15 · open the first message on its own page

Git shouldn't allow to push a new branch called HEAD

From: Daniele Segato <hidden>
Date: 2016-06-15 22:52:15

Hi all,


following from a discussion in IRC freenode #git between me, sitaram an
shruggar


step to reproduce:

$ mkdir /tmp/gitbug
$ cd /tmp/gitbug/

$ # create a fake remote repo
$ git init --bare remote.git

$ # clone it with the user that will generate the bug
$ git clone remote.git buggenerator
$ cd buggenerator/
$ touch whatever
$ git add .
$ git commit -m "first commit"
$ git push origin master 

$ # now clone the same repo the other guy is the "victim" of this issue
$ cd ..
$ git clone remote.git victim

$ # time to create the remote HEAD branch
$ cd buggenerator/
$ git push origin HEAD:HEAD

$ # the remote refs has been created!
$ git ls-remote

$ # another commit
$ echo 'any change' >> whatever 
$ git commit -a -m "some change"
$ git push origin master 

$ # the refs/heads/HEAD is still where it was
$ git ls-remote

$ # now from the victim perspective
$ cd ../victim/

$ # every time executing a fetch he will get a force update
$ # or maybe even an error, seen it my real repo, don't know how
$ # to reproduce
$ git fetch 
$ git fetch 
$ git ls-remote
$ git fetch 
$ git ls-remote
$ git branch -a



full console log:

mastro@mastroc3 ~  $ mkdir /tmp/gitbug
mastro@mastroc3 ~  $ cd /tmp/gitbug/
mastro@mastroc3 /tmp/gitbug  $ git init --bare remote.git
Initialized empty Git repository in /tmp/gitbug/remote.git/
mastro@mastroc3 /tmp/gitbug  $ git clone remote.git buggenerator
Cloning into buggenerator...
done.
warning: You appear to have cloned an empty repository.
mastro@mastroc3 /tmp/gitbug  $ cd buggenerator/
mastro@mastroc3 /tmp/gitbug/buggenerator (master #) $ touch whatever
mastro@mastroc3 /tmp/gitbug/buggenerator (master #) $ git add .
mastro@mastroc3 /tmp/gitbug/buggenerator (master #) $ git commit -m
"first commit"
[master (root-commit) 11d0a12] first commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 whatever
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ git push origin
master 
Counting objects: 3, done.
Writing objects: 100% (3/3), 213 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /tmp/gitbug/remote.git
 * [new branch]      master -> master
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ cd ..
mastro@mastroc3 /tmp/gitbug  $ git clone remote.git victim
Cloning into victim...
done.
mastro@mastroc3 /tmp/gitbug  $ cd buggenerator/

# now creating the HEAD remote branch

mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ git push origin
HEAD:HEAD
Total 0 (delta 0), reused 0 (delta 0)
To /tmp/gitbug/remote.git
 * [new branch]      HEAD -> HEAD
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ git ls-remote
From /tmp/gitbug/remote.git
11d0a122125e50e78c7aa4aa81a3d6090dba648e	HEAD
11d0a122125e50e78c7aa4aa81a3d6090dba648e	refs/heads/HEAD <-----
shouldn't be there!
11d0a122125e50e78c7aa4aa81a3d6090dba648e	refs/heads/master
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ echo 'any change' >>
whatever 
mastro@mastroc3 /tmp/gitbug/buggenerator (master *) $ git commit -a -m
"some change"
[master 77852ef] some change
 1 files changed, 1 insertions(+), 0 deletions(-)
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ git push origin
master 
Counting objects: 5, done.
Writing objects: 100% (3/3), 253 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /tmp/gitbug/remote.git
   11d0a12..77852ef  master -> master
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ git ls-remote
From /tmp/gitbug/remote.git
77852effa972187d60d4c75145198991f1c0f868	HEAD
11d0a122125e50e78c7aa4aa81a3d6090dba648e	refs/heads/HEAD
77852effa972187d60d4c75145198991f1c0f868	refs/heads/master
mastro@mastroc3 /tmp/gitbug/buggenerator (master) $ cd ../victim/
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
remote: Counting objects: 5, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /tmp/gitbug/remote
   11d0a12..77852ef  master     -> origin/master
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
From /tmp/gitbug/remote
 + 77852ef...11d0a12 HEAD       -> origin/HEAD  (forced update)
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
From /tmp/gitbug/remote
   11d0a12..77852ef  master     -> origin/master
mastro@mastroc3 /tmp/gitbug/victim (master) $ git ls-remote
From /tmp/gitbug/remote.git
77852effa972187d60d4c75145198991f1c0f868	HEAD
11d0a122125e50e78c7aa4aa81a3d6090dba648e	refs/heads/HEAD
77852effa972187d60d4c75145198991f1c0f868	refs/heads/master
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
From /tmp/gitbug/remote
 + 77852ef...11d0a12 HEAD       -> origin/HEAD  (forced update)
mastro@mastroc3 /tmp/gitbug/victim (master) $ git ls-remote
From /tmp/gitbug/remote.git
77852effa972187d60d4c75145198991f1c0f868	HEAD
11d0a122125e50e78c7aa4aa81a3d6090dba648e	refs/heads/HEAD
77852effa972187d60d4c75145198991f1c0f868	refs/heads/master
mastro@mastroc3 /tmp/gitbug/victim (master) $ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master




this can be fixed with:

git push --delete origin HEAD
(or git push origin :HEAD)

then
git remote prune origin



But I think that git shouldn't allow the remote HEAD reference to be
created in the first place

regards,
Daniele

Re: Git shouldn't allow to push a new branch called HEAD

From: Daniele Segato <hidden>
Date: 2016-06-15 22:52:15

On Fri, 2011-10-14 at 13:31 +0200, Daniele Segato wrote:
Hi all,


following from a discussion in IRC freenode #git between me, sitaram an
shruggar


step to reproduce:

$ mkdir /tmp/gitbug
$ cd /tmp/gitbug/

$ # create a fake remote repo
$ git init --bare remote.git

$ # clone it with the user that will generate the bug
$ git clone remote.git buggenerator
$ cd buggenerator/
$ touch whatever
$ git add .
$ git commit -m "first commit"
$ git push origin master 

$ # now clone the same repo the other guy is the "victim" of this issue
$ cd ..
$ git clone remote.git victim

$ # time to create the remote HEAD branch
$ cd buggenerator/
$ git push origin HEAD:HEAD

$ # the remote refs has been created!
$ git ls-remote

$ # another commit
$ echo 'any change' >> whatever 
$ git commit -a -m "some change"
$ git push origin master 

$ # the refs/heads/HEAD is still where it was
$ git ls-remote

$ # now from the victim perspective
$ cd ../victim/

$ # every time executing a fetch he will get a force update
$ # or maybe even an error, seen it my real repo, don't know how
$ # to reproduce
$ git fetch 
$ git fetch 
$ git ls-remote
$ git fetch 
$ git ls-remote
$ git branch -a
This should also help understanding what happen in the "victim" local
repo at every fetch:

mastro@mastroc3 /tmp/gitbug/victim (master) $ git br -av
* master                11d0a12 [behind 1] first commit
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 77852ef some change
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
From /tmp/gitbug/remote
 + 77852ef...11d0a12 HEAD       -> origin/HEAD  (forced update)
mastro@mastroc3 /tmp/gitbug/victim (master) $ git br -av
* master                11d0a12 first commit
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 11d0a12 first commit


regards,
Daniele

Re: Git shouldn't allow to push a new branch called HEAD

From: P Rouleau <hidden>
Date: 2016-06-15 22:52:16

Daniele Segato <daniele.segato <at> gmail.com> writes:
Hi all,

following from a discussion in IRC freenode #git between me, sitaram an
shruggar

step to reproduce:

$ # time to create the remote HEAD branch
$ cd buggenerator/
$ git push origin HEAD:HEAD

But I think that git shouldn't allow the remote HEAD reference to be
created in the first place
Maybe git should also refuse to create a local branch named HEAD. I made a
mistake recently where I used something likes this:

for B in $(git branch -a|grep "remotes/origin/"); do git co -t $B ; done

After that, git st was giving a warning about an ambiguous HEAD ref. Hopefully,
a simple "git branch -d HEAD" fixed it once I found the problem.

P.Rouleau

Re: Git shouldn't allow to push a new branch called HEAD

From: Daniele Segato <hidden>
Date: 2016-06-15 22:52:28

On Fri, 2011-10-14 at 13:35 +0200, Daniele Segato wrote:
On Fri, 2011-10-14 at 13:31 +0200, Daniele Segato wrote:
quoted
Hi all,


following from a discussion in IRC freenode #git between me, sitaram an
shruggar


step to reproduce:

$ mkdir /tmp/gitbug
$ cd /tmp/gitbug/

$ # create a fake remote repo
$ git init --bare remote.git

$ # clone it with the user that will generate the bug
$ git clone remote.git buggenerator
$ cd buggenerator/
$ touch whatever
$ git add .
$ git commit -m "first commit"
$ git push origin master 

$ # now clone the same repo the other guy is the "victim" of this issue
$ cd ..
$ git clone remote.git victim

$ # time to create the remote HEAD branch
$ cd buggenerator/
$ git push origin HEAD:HEAD

$ # the remote refs has been created!
$ git ls-remote

$ # another commit
$ echo 'any change' >> whatever 
$ git commit -a -m "some change"
$ git push origin master 

$ # the refs/heads/HEAD is still where it was
$ git ls-remote

$ # now from the victim perspective
$ cd ../victim/

$ # every time executing a fetch he will get a force update
$ # or maybe even an error, seen it my real repo, don't know how
$ # to reproduce
$ git fetch 
$ git fetch 
$ git ls-remote
$ git fetch 
$ git ls-remote
$ git branch -a
This should also help understanding what happen in the "victim" local
repo at every fetch:

mastro@mastroc3 /tmp/gitbug/victim (master) $ git br -av
* master                11d0a12 [behind 1] first commit
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 77852ef some change
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
From /tmp/gitbug/remote
 + 77852ef...11d0a12 HEAD       -> origin/HEAD  (forced update)
mastro@mastroc3 /tmp/gitbug/victim (master) $ git br -av
* master                11d0a12 first commit
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 11d0a12 first commit

Hi again,

I'm aware my request has been ignored for a good reason but I would
appreciate someone stepping in and explaining to me why this is not a
bug or why it has been ignored.

Thanks.

Regards,
Daniele Segato

Re: Git shouldn't allow to push a new branch called HEAD

From: Michael Haggerty <hidden>
Date: 2016-06-15 22:52:28

On 11/14/2011 10:07 AM, Daniele Segato wrote:
On Fri, 2011-10-14 at 13:35 +0200, Daniele Segato wrote:
quoted
On Fri, 2011-10-14 at 13:31 +0200, Daniele Segato wrote:
quoted
following from a discussion in IRC freenode #git between me, sitaram an
shruggar


step to reproduce:

$ mkdir /tmp/gitbug
$ cd /tmp/gitbug/

$ # create a fake remote repo
$ git init --bare remote.git

$ # clone it with the user that will generate the bug
$ git clone remote.git buggenerator
$ cd buggenerator/
$ touch whatever
$ git add .
$ git commit -m "first commit"
$ git push origin master 

$ # now clone the same repo the other guy is the "victim" of this issue
$ cd ..
$ git clone remote.git victim

$ # time to create the remote HEAD branch
$ cd buggenerator/
$ git push origin HEAD:HEAD

$ # the remote refs has been created!
$ git ls-remote

$ # another commit
$ echo 'any change' >> whatever 
$ git commit -a -m "some change"
$ git push origin master 

$ # the refs/heads/HEAD is still where it was
$ git ls-remote

$ # now from the victim perspective
$ cd ../victim/

$ # every time executing a fetch he will get a force update
$ # or maybe even an error, seen it my real repo, don't know how
$ # to reproduce
$ git fetch 
$ git fetch 
$ git ls-remote
$ git fetch 
$ git ls-remote
$ git branch -a
This should also help understanding what happen in the "victim" local
repo at every fetch:

mastro@mastroc3 /tmp/gitbug/victim (master) $ git br -av
* master                11d0a12 [behind 1] first commit
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 77852ef some change
mastro@mastroc3 /tmp/gitbug/victim (master) $ git fetch 
From /tmp/gitbug/remote
 + 77852ef...11d0a12 HEAD       -> origin/HEAD  (forced update)
mastro@mastroc3 /tmp/gitbug/victim (master) $ git br -av
* master                11d0a12 first commit
  remotes/origin/HEAD   -> origin/master
  remotes/origin/master 11d0a12 first commit
I'm aware my request has been ignored for a good reason but I would
appreciate someone stepping in and explaining to me why this is not a
bug or why it has been ignored.
This is a nice little bug.

I'm sure that you noticed that running "git fetch" repeatedly from the
"victim" repository alternates between two behaviors (I'm using 1.7.7.2):
$ git fetch
From /home/mhagger/tmp/gitbug/remote
 + 6bf3df1...4c9ebba HEAD       -> origin/HEAD  (forced update)
$ git for-each-ref
4c9ebba3c0618bd6238a810013da4a8cd4f2213b commit	refs/heads/master
4c9ebba3c0618bd6238a810013da4a8cd4f2213b commit	refs/remotes/origin/HEAD
4c9ebba3c0618bd6238a810013da4a8cd4f2213b commit	refs/remotes/origin/master
$ git fetch
From /home/mhagger/tmp/gitbug/remote
   4c9ebba..6bf3df1  master     -> origin/master
$ git for-each-ref
4c9ebba3c0618bd6238a810013da4a8cd4f2213b commit	refs/heads/master
6bf3df178cd92ca72625ae5bda9206c4333fd807 commit	refs/remotes/origin/HEAD
6bf3df178cd92ca72625ae5bda9206c4333fd807 commit	refs/remotes/origin/master
$ git fetch
From /home/mhagger/tmp/gitbug/remote
 + 6bf3df1...4c9ebba HEAD       -> origin/HEAD  (forced update)
$ git fetch
From /home/mhagger/tmp/gitbug/remote
   4c9ebba..6bf3df1  master     -> origin/master
The whole time, victim's .git/HEAD contains "ref: refs/heads/master",
.git/refs/remotes/origin/HEAD contains "ref:
refs/remotes/origin/master", and its packed-refs file contains

# pack-refs with: peeled
4c9ebba3c0618bd6238a810013da4a8cd4f2213b refs/remotes/origin/master

In "remote.git", refs/heads/HEAD contains not a symbolic reference but
the explicit SHA1 "4c9ebba...".  This is of course not affected by
running "git fetch" in the "victim" tree.  Deleting this file makes the
problem go away.


Given that this problem seems to be in the remote protocol rather than
in the refs API, I think I'll stop working on this.  I hope that my
observations are helpful to somebody.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

Re: Git shouldn't allow to push a new branch called HEAD

From: Jeff King <hidden>
Date: 2016-06-15 22:52:28

On Mon, Nov 14, 2011 at 11:45:46AM +0100, Michael Haggerty wrote:
The whole time, victim's .git/HEAD contains "ref: refs/heads/master",
.git/refs/remotes/origin/HEAD contains "ref:
refs/remotes/origin/master", and its packed-refs file contains

# pack-refs with: peeled
4c9ebba3c0618bd6238a810013da4a8cd4f2213b refs/remotes/origin/master

In "remote.git", refs/heads/HEAD contains not a symbolic reference but
the explicit SHA1 "4c9ebba...".  This is of course not affected by
running "git fetch" in the "victim" tree.  Deleting this file makes the
problem go away.


Given that this problem seems to be in the remote protocol rather than
in the refs API, I think I'll stop working on this.  I hope that my
observations are helpful to somebody.
I didn't recreate the test situation and look closely, but my impression
is that this isn't a code bug at all, but rather a design problem in the
way we store remote namespaces. That is, we make "refs/remotes/foo/HEAD"
a symbolic ref with special meaning, but then fetch into it from the
remote's refs/heads namespace, writing remote's HEAD branch into
whatever our HEAD symref points to.

So one solution is to block fetching of remote branches called HEAD
(which I would be OK with). But another is to use a more sensible layout
for representing the remote refs, like:

   refs/remotes/origin/HEAD            (a symbolic ref)
   refs/remotes/origin/heads/master
   refs/remotes/origin/tags/v1.0

etc. Then the namespaces are properly separated, and the magic remote
"HEAD" symref is not in the way.

Obviously there's a lot more to it than just tweaking the default fetch
refspecs. The ref lookup rules need to be changed to take this into
account. There was some discussion about this over the summer (under the
subject of possible "1.8.0" changes), but I don't think any work has
been done.

-Peff
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help