Re: Strange behaviour when pushing a commit object to remote's refs/HEAD
- From
Karthik Nayak <karthik.188@gmail.com>
- Date
- Jan 16, 2024, 09:54 UTC
- Message-ID
- <CAOLa=ZS8YBhzaYx=9016KxErsMsazsF09rcuPs=-WpEGjV+ruw@mail.gmail.com>
- In-Reply-To
- <mafs0fryypg82.fsf@yadavpratyush.com>
Pratyush Yadav <me@yadavpratyush.com> writes:
> Hi, >
Hello,
Show 18 quoted lines
> I ran into a strange Magit bug, where when I ran magit-show-refs on a > particular repo it threw an error. The details of the Magit bug are not > very interesting, but when attempting to reproduce it, I also saw git > misbehaving for such repos. > > The strange behaviour happens when you push a commit object to remote's > refs/HEAD instead of pushing a symbolic ref. Such a repository can be > found at https://github.com/prati0100/magit-reproducer. I roughly used > the below steps to create such a repo: > > $ git init > $ echo 1 > foo && git add foo && git commit > $ echo 2 > bar && git add bar && git commit > $ git push > $ git checkout 79264c3 > $ echo 2.1 > bar && git add bar && git commit > $ git push origin 707a3d5:refs/heads/HEAD >
Just to note here that pushing to "refs/heads/HEAD" is not actually updating the remote repositories $GIT_DIR/HEAD file, rather it creates a new reference $GIT_DIR/refs/heads/HEAD.
With this understanding you'll see that this is not a bug, because the remote HEAD was never updated, but only a new branch called HEAD was created [0].
Show 18 quoted lines
> Now with such a repo, if you do `git log --all --oneline` it would look > something like: > > 707a3d5 (origin/HEAD) 2.1 > 86e1c97 (HEAD -> main, origin/main) 2 > 79264c3 1 > > And running `git for-each-ref --format='%(symref:short),%(refname:short),%(refname),%(subject)' refs/remotes/origin` gives: > > ,origin,refs/remotes/origin/HEAD,2.1 > ,origin/main,refs/remotes/origin/main,2 > > All well and good so far. Now delete the repo and attempt to clone it. > This time `git log --all --oneline` gives: > > 86e1c97 (HEAD -> main, origin/main, origin/HEAD) 2 > 79264c3 1 >
This is expected since you cloned the repository and you got the default branch 'main'.
Show 9 quoted lines
> And running `git for-each-ref --format='%(symref:short),%(refname:short),%(refname),%(subject)' refs/remotes/origin` gives: > > origin/main,origin,refs/remotes/origin/HEAD,2 > ,origin/main,refs/remotes/origin/main,2 > > So suddenly the remote's HEAD becomes origin/main (symbolic ref) and the > commit (707a3d5, "2.1") is nowhere to be found. It neither shows up in > `git rev-list --all` nor in `git log --all`. The files and trees > associated with it also do not show up in `git rev-list --all --object`.
Because rev-list's `--all`, iterates over all refs. Since you only cloned, the HEAD branch is not pulled.
Everything else is a consequence of the subtle but important difference between updating $GIT_DIR/HEAD vs creating $GIT_DIR/refs/heads/HEAD.
[0]: https://github.com/prati0100/magit-reproducer/branches/all
Thanks, Karthik