What happens when I push from a tracking branch in Git to a different remote branch?

Say I have a tracking branch called devo-1 that tracks the remote’s devo-1 branch. Suppose there’s another branch in the same remote, called devo-2. I now perform the following:

  1. git checkout devo-1
  2. git fetch origin
  3. git pull origin devo-2
  4. git push origin devo-2

My questions:

  • git show on a sepecific file return 'fatal: bad object'
  • git checkout all the files
  • Partial Git deployment strategy?
  • Git checkout from freshly cloned repository into a branch leads to unstaged changes in that branch
  • After a git reset, unreachable commit not removed
  • Git kraken menu bar is missing
    • At step 2, this should update all origin/devo-* remote-tracking branches, correct?
    • At step 3, this should get updates from only origin devo-2 (and not devo-1), correct?
    • At step 4, this should push changes in devo-1 to only origin devo-2, correct?

    Thanks!

  • Git submodule absolute worktree path config
  • How do I get a log for submodule ref pointer?
  • What does git log show me?
  • Finding a Git commit that introduced a string in any branch
  • git describe with two tags on the same commit
  • Managing phonegap / cordova project with git
  • 4 Solutions collect form web for “What happens when I push from a tracking branch in Git to a different remote branch?”

    Short version: 1: yes, 2: maybe, 3: no.


    Git’s terminology is twisty and confusing. You don’t push to a “remote branch”, you push to a branch on a remote. Seems like a silly distinction but because the terminology is confusing, it’s important to make sure. (Just to be even more confusing, these “branches” all refer to labels attached to repositories, rather than the data structures one builds from the commit graphs contained in those repositories; but parts of those structures are also called “branches” at various times.)

    To make things worse, git fetch, git pull, and git push are not quite symmetric, either.

    We start out in your own devo-1 branch (because of git checkout devo-1), although that does not matter until git pull invokes git merge below.

    Then, assuming a standard setup (not a mirror or whatever):

    git fetch origin
    

    calls up the remote git on the internet-phone (or whatever), asks him “hey, what branch labels do you have”, copies over commits and such as needed, and sticks a copy of his (local) branch labels in your (local) “remote-branch” labels under your origin/ name-space. That is, origin/devo-1 and origin/devo-2 are both updated—I assume both exist on origin—along with anything else that can be, while your git has this chance.

    (The answer to your first question is “yes”.)

    The next command:

    git pull origin devo-2
    

    just runs a shell script, which in turn runs two commands:

    • git fetch (with some arguments), then
    • either git merge or git rebase, depending on your pull configuration. I’m going to assume the former.

    The first sub-part calls up the remote git on the internet-phone again. This time it only brings over new stuff in the supplied branch, i.e., their copy of devo-2. It’s pretty likely there’s nothing new there yet (you just did a full fetch), but if there is anything new, it then drops the new SHA-1 into the special FETCH_HEAD file, but does not1 update your “remote branch” copy in origin/devo-2.

    The second sub-part runs git merge to merge in their latest version. This is the moral equivalent2 of doing git merge origin/devo-2. So now your devo-1 is merged with the latest commit in their devo-2, as recorded in FETCH_HEAD.

    (Or, if you’re set up for rebase, it does that instead.)

    (The answer to your second question is “maybe, depending on precisely what you meant”.)

    Although you get any new commits and other SHA-1 goodies needed, they’re only written into FETCH_HEAD, unless you have a new (1.8.4 or later) git. (See footnote 1.)

    Last, your git push: you gave it two extra arguments, a remote and a refspec. The remote is origin, so that’s who it will call up on the internet-phone or whatever as before. The refspec, though: that’s devo-2, and that means devo-2:devo-2 which (since I assume you have a local devo-2 branch) means refs/heads/devo-2:refs/heads/devo-2.

    This takes your local devo-2 (not devo-1) and tries to send new stuff to the remote (he gets a chance to reject them) and point his devo-2 branch label to the new tip commit.

    (The answer to your third question is “no”.)

    In order to push what’s in your devo-1 to their devo-2, you need:

    git push origin devo-1:devo-2
    

    The refspec here means: “Send their git the SHA-1 you find by looking up my devo-1, and ask them to write it to their devo-2.”


    1Unless you have git 1.8.4 or newer, and then it does update origin/devo-2. Fortunately, this doesn’t matter here: even if there was new stuff, the next step uses FETCH_HEAD to refer to it, rather than using origin/devo-2.

    2If you have git 1.8.4 or newer, it’s the real equivalent. Otherwise it depends on whether the second fetch actually brought new stuff in.

    At step 2, this should update all origin/devo-* remote-tracking branches, correct?

    Correct. (Well, any remote tracking branches. Not just those that start with “devo”)

    At step 3, this should get updates from only origin devo-2 (and not devo-1), correct?

    Correct. (Well, the remote devo-2 branch will be merged/rebased with your HEAD).

    At step 4, this should push changes in devo-1 to only origin devo-2, correct?

    Incorrect. git push origin devo-1:devo-2 is what you’re looking for.

    git push origin devo-2 is basically saying “push my local devo-2 branch to the remote devo-2 branch”, or git push origin devo-2:devo-2.

    Step 2 – yes git-fetch will update all remote branches (unless you provide a refspec argument to limit what it fetches).

    Step 3 – no, git-pull is essentially the same as git-fetch + git-merge, and the merge operation will operate on the current branch. So in this example the current branch is devo-1 and the command would then merge devo-2 into devo-1.

    Step 4, no this will push your local devo-2 changes to origin/devo-2.

    • git fetch will not only update remote tracking branches, but all remote branches of that remote. Tracking usually means that a local branch belongs to a certain remote branch and consider that as the default, and supply additional status information.

    • git pull origin devo-2 will fetch again for devo-2 and then merge the remote branch (origin/devo-2) into the current branch. So as you have checked out the local devo-1 branch before, you will essentially merge the remote’s devo-2 into that branch.

    • git push origin devo-2 will be equivalent to git push origin devo-2:devo-2 which means that this will push your local devo-2 to the remote’s devo-2. So no, your local and currently checked out branch devo-1 will not be used for anything.

    Git Baby is a git and github fan, let's start git clone.