Search code examples
gitgithubpermissionstracking

Proper git remote tracking practice


The GitHub forking documentation outlines that the best remote tracking practice for when you have your own fork is to have origin as your own branch and upstream as the branch that you forked from:

$ git remote -v
origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch)
upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)

Ideally, I would like to be able to track from the upstream branch so that I can see when I need to fetch code from the remote to rebase with my current version, but by default I would also like to push my code to the origin repository where I can make a pull-request to the repo I forked from (instead of attempting to push to the fork and getting a Permission denied: 403 error).

Is there a "best" way to do this?

I couldn't find a definitive answer to this question after searching, please feel free to link me if this answer has been posted before and I just haven't found it. Thank you!


Solution

  • So I found a potential interesting solution to this problem.

    One thing I didn't really think about but just noticed were the (fetch) and (push) parentheses after a remote URL listing from the verbose git remote command:

    $ git remote -v
    origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
    origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
    upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch)
    upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)
    

    What if you could have a single remote: origin, that has a different URL for fetch and push. That way you can track a default remote but push to a different one, also by default. I did some research and it turns out this is very possible.

    In the .git/config file you can keep the fetch and url parameters the same, but throw in an additional pushurl parameter for the forked (upstream) repository.

    [remote "origin"]
      fetch = +refs/heads/*:refs/remotes/origin/*
      url = https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
      pushurl = https://github.com/YOUR_USERNAME/YOUR_FORK.git
    

    This leads to the following output:

    $ git remote -v
    origin  https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
    origin  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch)
    

    Which may not be good or proper practice but it certainly makes it much more cohesive. Would love to hear what you guys think of this!