Search code examples
gitgit-workflow

How does Git detect type of workflows: central or non-central


In Git-config you can see:

simple - in centralized workflow, work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one.

When pushing to a remote that is different from the remote you normally pull from, work as current.

So Git must decide between working like upstream or current. But how Git detect type of workflow? Does Git think a workflow is centralized if understands we want to communicate with a bare repository?


Solution

  • The description of upstream in the very same documentation you linked gives you the answer to your question.

    This mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow).

    So "central workflow" in this context is defined as "you push to the same repo you get your latest upstream changes from usually", no matter whether you use rebase or merge. (pull = fetch+merge or fetch+rebase, depending on configuration and parameters)

    Whether you have "central workflow" or not, is in this context possibly different for each push call. If you have a remote tracking branch (upstream branch) set for your local branch you are about to push, then this tracking branch is where you usually get your updates from (it is the one you track) so if you do a rebase or merge (or pull of course, as it is fetch+merge or fetch+pull) without specifiying what to rebase onto or what to merge in, then the remote tracking branch is used.

    Now if you push, Git know whether you push to the same branch of the same remote that you have set up as tracking branch for your local branch about to be pushed. If this matches, you have what is defined as "central workflow" in this context and upstream is used, if not or if no tracking branch is set up (also a case of "not"), current is used.

    The differences are:

    current:

    • Your local branch foo tracks remote branch bar/baz:
      • On push to any remote, you push to branch foo if you do not say otherwise.
    • Your local branch foo tracks remote branch bar/foo:
      • On push to any remote, you push to branch foo if you do not say otherwise.
    • Your local branch foo does not track any remote branch:
      • On push to any remote, you push to branch foo if you do not say otherwise.

    upstream:

    • Your local branch foo tracks remote branch bar/baz:
      • On push to remote bar, you push to branch baz if you do not say otherwise.
      • On push to any other remote, you get an error saying you should specify exactly where to push to as the remote is not the upstream one
    • Your local branch foo tracks remote branch bar/foo:
      • On push to remote bar, you push to branch foo if you do not say otherwise.
      • On push to any other remote, you get an error saying you should specify exactly where to push to as the remote is not the upstream one
    • Your local branch foo does not track any remote branch:
      • On push to any remote, you get an error saying you should set your upstream branch

    simple:

    • Your local branch foo tracks remote branch bar/baz:
      • On push to remote bar, you get an error that tells you to push explicitly as the names do not match
      • On push to any other remote, you push to branch foo.
    • Your local branch foo tracks remote branch bar/foo:
      • On push to any remote, you push to branch foo if you do not say otherwise.
    • Your local branch foo does not track any remote branch:
      • On push to any remote, you get an error saying you should set your upstream branch