Why is `git push` to non-bare remote not the dual of `git fetch` from the remote

1k Views Asked by At

First, I understand the how related to pushing to non-bare git remotes, including the use of the git config option receive.denyCurrentBranch and other work arounds, so I'm NOT looking for answers such as those here:

This is more of a git implementation/representation/philosophical question.

Why can't a git push <remote> to a non-bare remote be the dual or essentially the same as a git fetch <source> from the remote? That way, my local working dir on the remote may be out of date (behind) the new content, and I might even have local changes (commits ahead, or even staged/unstaged/stashed/whatever), but that working dir is completely untouched by the push operation? If it did, then once on the remote, I could merge or rebase or whatevever necessary. In fact, that's exactly what is claimed by this kernel.org git faq entry.

Motiviation for this is really the same as everyone else who asks the how questions: I don't have any way to easily access the "source" of the push from the remote due to {firewall, nat, security} reasons.

Probably I'm missing some fundamental knowledge of how git really tracks things that "if I only understood XXXX", I'd know the answer; enlighten me, please.

1

There are 1 best solutions below

5
On BEST ANSWER

The problem is that pushing rewrites refs. HEAD is a synonym for the latest checkout, and rewriting that ref silently invalidates the worktree and index -- a commit in that repo will lose the pushed changes, with no indication that that's happened. Refusing the push is the simplest solution. If doing git pull at the destination isn't an option, then push to a throwaway and fix up the refs:

git push origin master:fakemaster
cd $origindir
git checkout -B master fakemaster
git branch -D fakemaster