As a consequence of the peer-to-peer semantics of Git repositories, all repositories are of equal stature. You can push to and fetch from development and bare repositories equally, as there is no fundamental implementation distinction between them. This symmetric design is critically important to Git, but it also leads to some unexpected behavior if you try to treat bare and development repositories as exact equals.
Recall that the git push command does not check out files in the receiving repository. It simply transfers objects from the source repository to the receiving repository and then updates the corresponding refs on the receiving end.
In a bare repository, this behavior is all that can be expected, because there is no working directory that might be updated by checked-out files. That’s good. However, in a development repository that is the recipient of a push operation, it can later cause confusion to anyone using the development repository.
The push operation can update the repository state, including the
HEAD commit. That is, even though the developer at
the remote end has done nothing, the branch refs and
HEAD might change, becoming out of sync with the
checked-out files and index.
A developer who is actively working in a repository into which an
asynchronous push happens will not see the push But a subsequent commit
by that developer will occur on an unexpected
HEAD, creating an odd history. A forced push will lose pushed commits from the ...