Search code examples
gitgithubgit-mergegit-pullgit-fetch

Why does git not fetch the pull request I merged in GitHub?


I'm having some git trouble. My setup is as follows:

[workstation repo] -origin-> [network drive bare repo] -origin-> [GitHub]

I just accepted my first pull request on GitHub (this one) and merged it to master. Now I want to pull it to my workstation. So I do git fetch on the network drive, and then git pull on my workstation, but on my workstation git says 'Already up-to-date' and refuses to merge the change (I checked, it's not in my workspace).

The output of git branch -vv on the network drive includes the line:

* master                    0fe40e2 [origin/master: behind 2] Some small code improvements

The output of git branch -vv on the workstation repo includes the line:

* master         0fe40e2 [origin/master] Some small code improvements

The actual commit they should be pointing to is 3388641. It looks like in the bare repo on the network drive the master branch is somehow behind origin/master. I have no idea how this situation arose, or how to fix it. I can't use git pull or git reset since it is a bare repo.

Does anyone know how I can determine what the problem is and how to fix it?


Solution

  • I'm not sure what the purpose of this separate bare clone is (the bare clone being the one you say is on a network drive), but if it's not a mirror clone—mirrors being a particular type of bare clone—it has its own branch names, independent of all other Git repositories.1 Therefore, you'll need to tell it to update any particular branch if and when you want it to slave itself to some other Git repository.

    I can't use git pull or git reset since it is a bare repo ...

    It is true that you cannot use git pull, because it is a bare repository and git pull means run git fetch, then run a second Git command and that second Git command is always one that needs a work-tree. However, it's not the case that you cannot use git reset. What you cannot do is do a mixed or hard reset:

    $ git reset
    fatal: mixed reset is not allowed in a bare repository
    $ git reset --hard
    fatal: this operation must be run in a work tree
    

    A --soft reset is, however, allowed:

    $ git reset --soft
    $ 
    

    so one way to move the local master to match origin/master is:

    $ git reset --soft origin/master
    

    However, the most appropriate thing is probably to either stop using this bare repository entirely, or use a mirror clone (see footnote 1).


    1Technically, even a mirror clone has its own branch names. The key difference between a non-mirror bare clone and a mirror bare clone is that the mirror clone has all of its branch names slaved to its origin.2 Specifically, the fetch configuration for a mirror clone is:

    [remote "origin"]
        fetch = +refs/heads/*:refs/heads/*
    

    rather than the standard:

    [remote "origin"]
        fetch = +refs/heads/*:refs/remotes/origin/*
    

    The standard fetch setting means that git fetch run in such a clone updates all the refs/remotes/origin/* names to match origin's refs/heads/* names. The nonstandard mirror setting means that git fetch run in a mirror clone forcibly updates all of the refs/heads/* names, immediately forgetting (and thereby losing any commits solely reachable from) its own branch names in favor of using the fetched names instead. That's what makes the mirror a mirror: it drops any commits that were exclusive to its own branches by replacing its own branch name commit hashes with whatever it saw on the remote.

    2The description above assumes the standard remote name origin. If you used some other name, everything still holds, it's just that instead of origin, the string literal is whatever name you used.