Search code examples
gitgithubbranchgit-pullgit-remote

Transfer for branch to anotherRemote/branch except origin remote with Git


I have two remotes. One is origin and the other is another Remote. There is also the url that these two remotes have. My purpose is to transfer the codes from origin / master to test branch in anotherRemote.

My transactions.

$ git remote add anotherRemote <anotherRemote-url>
$ git remote -v
$ anotherRemote   <anotherRemote-url> (fetch)
$ anotherRemote   <anotherRemote-url> (push)
$ origin          <origin-url> (fetch)
$ origin          <origin-url> (push)
$ git fetch anotherRemote
$ git add .
$ git commit -m "initial commit"
$ git push anotherRemote testBranch

but i get the following error

error: src refspec testBranch does not match any
error: failed to push some refs to '<anotherRemote-url>'

Solution

  • This command:

    git push anotherRemote testBranch
    

    is short for:

    git push anotherRemote testBranch:testBranch
    

    That is, your Git will:

    1. Look up the left hand side of testBranch:testBranch to find a commit hash ID.
    2. Assuming step 1 works, contact the Git that answers at the URL stored under the name anotherRemote and send the commit(s) that go with that hash ID.
    3. Assuming step 2 works, ask that other Git to set its branch name testBranch to the commit hash ID found in step 1.

    But you don't have a branch named testBranch, so step 1 simply fails. (You could create this branch name, but you do not have to do so.)

    My purpose is to transfer the codes from origin/master to test branch in anotherRemote.

    The name origin/master, in your own Git repository, is a way for your Git to find the hash ID of the a particular commit.1 This name is usable on the left side of the source:destination syntax for git push. There is one small glitch though. You might therefore wish to use:

    git push anotherRemote origin/master:refs/heads/testBranch
    

    This invokes the same three-step process above, but instead of trying to find the name testBranch in your own repository, it uses the name origin/master in your own repository to find the correct commit hash ID.

    Note that the right hand side is now refs/heads/testBranch instead of just testBranch. This is the full spelling of the branch name testBranch. The reason we now have to use the full spelling, instead of the simple abbreviation, is that git push no longer knows that we want to work with branch names. We could, for instance, mean to ask the Git over at anotherRemote to create a tag name.

    Using the full spelling like this tells our Git that we want it to ask the other Git to create a branch name. Without this, we get the following:

    $ git push origin origin/xyz:newbranch
    error: The destination you provided is not a full refname (i.e.,
    starting with "refs/"). We tried to guess what you meant by:
    
    - Looking for a ref that matches 'newbranch' on the remote side.
    - Checking if the <src> being pushed ('refs/remotes/origin/xyz')
      is a ref in "refs/{heads,tags}/". If so we add a corresponding
      refs/{heads,tags}/ prefix on the remote side.
    
    Neither worked, so we gave up. You must fully qualify the ref.
    hint: The <src> part of the refspec is a commit object.
    hint: Did you mean to create a new branch by pushing to
    hint: 'refs/remotes/origin/xyz:refs/heads/newbranch'?
    error: failed to push some refs to <url>
    

    This very long error message is Git's way of saying: please use refs/heads/newbranch here.


    1The commit hash ID your Git finds here depends on the last time you had your Git talk to the Git at origin. When you run git fetch origin, your Git calls up their Git. Their Git lists out their branch names and the commit hash IDs that go with each name. Your Git then gets those commits, if you don't already have them, and then updates your origin/* names based on their branch names.

    The fact that your Git updates your origin/master (remote-tracking name) based on their master (branch name) is why many people call these remote-tracking branch names. They're not branch names, though. Branch names start with refs/heads/ internally, and these remote-tracking names have a full spelling that starts with refs/remotes/. That is, your master branch is short for refs/heads/master, for instance; your origin/master is short for refs/remotes/origin/master.

    When you run git branch -r, your Git displays your remote-tracking names with refs/remotes/ stripped off the front. When you run git branch -r, your Git displays your remote-tracking names with only refs/ stripped off the front, so that you will see remotes/origin/master instead of origin/master. The full name is still refs/remotes/origin/master: what has changed is how much of this boring full name Git took off to make the name seem more exciting.