1

I cloned a brand-new repo from our server. I then pulled a new branch from origin. I made a few changes and committed, but when I try to push, I get the "updates were rejected because the tip of your current branch is behind" error. But it's not - it's a brand-new clone, and there have not been any commits made by other devs in the interim. I've tried doing git pull --rebase as suggested here, but it just tells me my branch is already up-to-date.

How can I resolve this issue?

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (master)
$ git fetch origin

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (master)
$ git checkout -b estrom/PH-19312 origin/release-18.9.0
Branch estrom/PH-19312 set up to track remote branch release-18.9.0 from origin.
Switched to a new branch 'estrom/PH-19312'

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ gitk

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ git commit -am "PH-19312 hide calories for literacy item in order history"
[estrom/PH-19312 5ace4de] PH-19312 hide calories for literacy item in order history
 1 file changed, 2 insertions(+)

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ git push
To ssh://stash.mycompany.com:7999/phi/qo6.git
 ! [rejected]        estrom/PH-19312 -> estrom/PH-19312 (non-fast-forward)
error: failed to push some refs to 'ssh://git@stash.mycompany.com:7999/phi/qo6.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ git pull --rebase
Current branch estrom/PH-19312 is up to date.

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ git pull --ff-only
remote: Counting objects: 28, done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 16 (delta 11), reused 0 (delta 0)
Unpacking objects: 100% (16/16), done.
From ssh://stash.mycompany.com:7999/phi/qo6
   34e51c0..6a7696a  PH-18381-18.10         -> origin/PH-18381-18.10
   fa0520a..6665db3  develop                -> origin/develop
 * [new branch]      PH-19548               -> origin/PH-19548
Already up-to-date.

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ git push
To ssh://stash.mycompany.com:7999/phi/qo6.git
 ! [rejected]        estrom/PH-19312 -> estrom/PH-19312 (non-fast-forward)
error: failed to push some refs to 'ssh://git@stash.mycompany.com:7999/phi/qo6.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$

ETA: result of `git branch -v -v --list estrom/PH-19312

estrom@T460-ESTROM MINGW64 /c/gitRepo/qo6 (estrom/PH-19312)
$ git branch -v -v --list estrom/PH-19312
* estrom/PH-19312 5ace4de [origin/release-18.9.0: ahead 1] PH-19312 hide calories for literacy item in order history
EmmyS
  • 11,892
  • 48
  • 101
  • 156
  • 1
    Please don't post screenshots of text. Copy-paste the text as text into the question and use the `{}` button to format it as code. – axiac May 23 '18 at 16:33
  • Apologies; I was having trouble copying from the bash window. Fixed. – EmmyS May 23 '18 at 16:43
  • Please also post the output of `git branch -v -v --list estrom/PH-19312`. – axiac May 23 '18 at 16:48
  • @axiac - I'm not familiar with the `-v -v`; what does that do? In any case, added. – EmmyS May 23 '18 at 16:51
  • `git help` followed by the command name (`git help branch`) is your best friend while learning Git. Also the [official documentation](https://git-scm.com/docs/git-branch). `-v` is short of `--verbose` and putting it twice in `git branch` makes it list the tracked remote branches. Only one `-v` displays the hash and the subject of the commit they point to. – axiac May 23 '18 at 16:57
  • OK, so that command shows that origin/release-18.9.0 is ahead by 1. But when I do `git pull --ff-only` it tells me my branch is already up to date. – EmmyS May 23 '18 at 17:03

3 Answers3

2

The output of git branch -v -v --list estrom/PH-19312 reveals the truth: the local branch estrom/PH-19312 is tracking the remote branch release-18.9.0 from origin which is, indeed, one commit ahead the local branch. This is why git push refuses to work.

On the other hand, you probably don't want to push to release-18.9.0 but to a remote branch named estrom/PH-19312. Then you make a pull request, it is reviewed and, if approved, it is merged into release-18.9.0.

The solution to the problem is simple: add --set-upstream to the git push command line to tell Git to use a branch with the same name on the remote repository:

git push --set-upstream origin estrom/PH-19314

The problem started when you created the local branch from a remote branch with a different name. To avoid this problem in the future add --no-track to the command line when you create branches using git checkout or git branch:

git checkout -b --no-track estrom/PH-19312 origin/release-18.9.0
axiac
  • 68,258
  • 9
  • 99
  • 134
  • I just tried the `--set-upstream` command, and got the exact same error as in my original post. And I'm not sure how this problem started, as I created my new branch the exact same way I've been doing it for years, and I've never had this issue before. – EmmyS May 23 '18 at 17:31
  • OK, I found my problem. Somehow I had already pushed a previous version of my changes, so there was a remote version of estrom/PH-19312, which I wasn't aware of. I deleted the remote version, deleted the local version, then pulled a new branch off origin/release-18.9.0. I was then able to commit and push my changes. Thanks for the help. – EmmyS May 23 '18 at 17:36
1

TL;DR

You probably want to change the upstream setting of your branch and rebase:

git branch --set-upstream-to origin/PH-19312
git rebase

Note that if your Git is very ancient, you won't have --set-upstream-to. You can use git branch --set-upstream but you have to be more verbose and use what looks like the wrong order of arguments (this is why modern Git has --set-upstream-to instead of --set-upstream):

git branch --set-upstream estrom/PH-19312 origin/estrom/PH-19312

Long

There are two problems interacting here, both stemming from the initial git checkout command.

The setup

Let's look first at this command:

$ git checkout -b estrom/PH-19312 origin/release-18.9.0
Branch estrom/PH-19312 set up to track remote branch release-18.9.0 from origin.
Switched to a new branch 'estrom/PH-19312'

The -b flag tells git checkout to create a new branch. The next word, estrom/PH-19312, supplies the name for the new branch. The subsequent origin/release-18.9.0 word specifies which commit to check out, and does one more thing when used with -b: it tells Git that, by default, the new branch name should have this name set as its upstream.

It's time to pause a bit and discuss what we mean by "branch" here (see also What exactly do we mean by "branch"?). In this case, the phrase branch estrom/PH-19312 means the name estrom/PH-19312 in the refs/heads name-space of references, and the "upstream" is an entry in .git/config concerning the name estrom/PH-19312. The branch name itself simply acts as a pointer to some existing commit, somewhere in the graph of "all commits ever made" that resides in your own Git repository. Only those who actually have a clone of the repository can enumerate all the commits, but just making some guesses from the output above, I will draw it like this, which is probably a little off but at least has something right :-) :

             o--o--o   <-- origin/develop
            /
...--o--o--o--o   <-- master (HEAD), origin/master
         \     \
          \     E   <-- origin/estrom/PH-19312
           \
            o--*   <-- origin/release-18.9.0

The round o nodes represent commits. I picked out a few particularly interesting commits and gave them a different symbol so that we can talk about them later.

You then ask Git (via git checkout -b ...) to:

  • Locate the commit to which origin/release-18.9.0 points: I've labeled that commit * here.
  • Extract that commit into the index (also known as the staging area and the cache; see other StackOverflow postings or Git documentation) and the work-tree.
  • Make a new label, estrom/PH-19312, pointing to this commit.

The result is that the graph itself is unchanged, but there is a new branch label, and your HEAD is now attached to that new branch label:

             o--o--o   <-- origin/develop
            /
...--o--o--o--o   <-- master, origin/master
         \     \
          \     E   <-- origin/estrom/PH-19312
           \
            o--*   <-- estrom/PH-19312 (HEAD), origin/release-18.9.0

At this point you do some work, successfully

You modified some files, git added them to the index, and git commited:

$ git commit -am "PH-19312 hide calories for literacy item in order history"
[estrom/PH-19312 5ace4de] PH-19312 hide calories for literacy item in order history
 1 file changed, 2 insertions(+)

This created a new commit in the commit graph, so let's update the drawing (I'm going to drop the top row entirely since I'm not using it):

...--o--o--o--o   <-- master, origin/master
         \     \
          \     E   <-- origin/estrom/PH-19312
           \
            o--*   <-- origin/release-18.9.0
                \
                 N   <-- estrom/PH-19312 (HEAD)

Note that the parent of new commit N is existing commit *. This is probably wrong: you started from release-18.9.0 as seen on origin (which your Git remembers as origin/release-18.9.0), rather than starting from estrom/PH-19312 as seen on origin.

The first failing Git command

At this point you ran:

$ git push
To ssh://stash.mycompany.com:7999/phi/qo6.git
 ! [rejected]        estrom/PH-19312 -> estrom/PH-19312 (non-fast-forward)

By default, git push tries to push based on the push.default setting. In this case, whatever you have set instructed your Git to push estrom/PH-19312. However, your push setting is neither simple nor upstream. It might be matching (especially if your Git is quite ancient, e.g., Git 1.7 to 1.9 instead of 2.0+). So your Git thought it should ask the other Git at ssh://stash.mycompany.com:7999/phi/qo6.git to have that other Git set its estrom/PH-19312 to point to commit N.

But their estrom/PH-19312 points to commit E. If they set their estrom/PH-19312 to point to commit N, they will lose commit E. Therefore they say: No, I will not do that: rejected: non-fast-forward. That's what non-fast-forward means: the label they have now points to some commit, and you're proposing that they remove some commit(s) from their branch while setting their branch to point to your new commit N.

Note that if you used simple as your push.default, your own Git would refuse to do the push, because the upstream name is release-18.9.0 (your origin/release-18.9.0). If you used upstream as your push.default setting, your Git would ask their Git to set their release-18.9.0—it's possible, but I think unlikely, that this is actually what you want.

Rebase does nothing because of the upstream setting

When you use git rebase or git pull --rebase, your Git tries to copy your commit N atop your origin/release-18.9.0. As you can see from the graph, your commit N already sits atop the commit to which origin/release-18.9.0 points, so rebase does nothing.

If you change the upstream setting for your estrom/PH-19312 branch to origin/estrom/PH-19312, git rebase will copy N to a new commit N' that sits atop origin/estrom/PH-19312:

...--o--o--o--o   <-- master, origin/master
         \     \
          \     E   <-- origin/estrom/PH-19312
           \     \
            \     N'  <-- estrom/PH-19312 (HEAD)
             \
              o--*   <-- origin/release-18.9.0
                  \
                   N   [abandoned]

This commit is now suitable to send to that other Git for it to add it its to estrom/PH-19312. I suspect this is what you want.

torek
  • 448,244
  • 59
  • 642
  • 775
0

First, try git pull --ff-only

Then push your changes

This will fast-forward your local copy of the branch so it's the same as the remote.

senthalan
  • 1,936
  • 3
  • 10
  • 19