Fix git “tip of your current branch is behind its remote counterpart” - 4 real-world solutions
Tags: git, productivity, beginners, gitflow
Published: 2019-03-25 07:57:49

---
title: Fix git “tip of your current branch is behind its remote counterpart” - 4 real-world solutions
published: true
tags: git, productivity, beginner, git-flow
canonical_url: https://codewithhugo.com/fix-git-failed-to-push-updates-were-rejected/
---

When working with `git` a selection of GitLab, GitHub, BitBucket and rebase-trigger-happy colleagues/collaborators, it’s a rite of passage to see a message like the following:

```
Pushing to git@github.com:some-project/some-repo.git
To git@github.com:some-project/some-repo.git
  ! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:some-project/some-repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

## What causes ”tip of your current branch is behind”?

Git works with the concept of local and remote branches. A local branch is a branch that exists in your local version of the git repository. A remote branch is one that exists on the remote location (most repositories usually have a remote called `origin`). A remote equates roughly to a place where you git repository is hosted (eg. a GitHub/GitLab/BitBucket/self-hosted Git server repository instance).

Remotes are useful to share your work or collaborate on a branch.

“the tip of your current branch is behind its remote counterpart” means that there have been changes on the remote branch that you don’t have locally.

There tend to be 2 types of changes to the remote branch: someone added commits or someone modified the history of the branch (usually some sort of rebase).

These 2 cases should be dealt with differently.

## How can you get your local branch back to a state that’s pushable?

We’re now going to explore how to achieve a state in the local branch where the remote won’t reject the push.

### 1. No rebase(s): merge the remote branch into local

In the message we can see:

> Updates were rejected because the tip of your current branch is behind its remote counterpart. Merge the remote changes (e.g. ‘git pull’) before pushing again.

So is it as simple as doing:

```
git pull
```

And solving any conflicts that arise.

We shouldn’t do this if someone has rebased on the remote. The history is different and a merge could have a nasty effect on the history. There will be a weird history with equivalent commits in 2 places plus a merge commit.

Read on for solutions to the “remote has been rebased” case.

### 2. Remote rebase + no local commits: force git to overwrite files on pull

If you don’t have any changes that aren’t on the remote you can just do:

> **Warning** : this is a destructive action, it overwrites all the changes in your local branch with the changes from the remote

```
git reset --hard origin/branch-name
```

This is of course very seldom the case but offers a path to the two following solutions.

Solutions 3. and 4. save the local changes somewhere else (the git stash or another branch). They reset the local branch from the origin using the above command. Finally they re-apply any local changes and send them up.

### 3. Remote rebase + local commits: soft git reset, stash, “hard pull”, pop stash, commit

Say you’ve got local changes (maybe just a few commits).

A simple way to use the knowledge from 2. is to do a “soft reset”.

#### Options to “soft reset”

Option 1, say the first commit you’ve added has sha `<first-commit-sha>` use:

> Note the `^` which means the commit preceding `<first-commit-sha>`

```
git reset <first-commit-sha>^ .
```

Option 2, if you know the number of commits you’ve added, you can also use the following, replace `3` with the number of commits you want to “undo”:

```
git reset HEAD~3 .
```

You should now be able to run `git status` and see un-staged (ie. “modified”) file changes from the local commits we’ve just “undone”.

#### Save your changes to the stash

Run `git stash` to save them to the stash (for more information [see git docs for stash](https://git-scm.com/docs/git-stash)).

If you run `git status` you’ll see the un-staged (“modified”) files aren’t there any more.

#### Run the hard pull as seen in the previous section

Run `git reset --hard origin/branch-name` as seen in 2.

#### Un-stash and re-commit your changes

To restore the stashed changes:

```
git stash pop
```

You can now use `git add` (hopefully with the `-p` option, eg. `git add -p .`) followed by `git commit` to add your local changes to a branch that the remote won’t reject on push.

Once you’ve added your changes, `git push` shouldn’t get rejected.

### 4. Remote rebase + local commits 2: checkout to a new temp branch, “hard pull” the original branch, cherry-pick from temp onto branch

That alternative to using stash is to branch off of the local branch, and re-apply the commits of a “hard pull”-ed version of the branch.

#### Create a new temp branch

To start with we’ll create a new temporary local branch. Assuming we started on branch `branch-name` branch (if not, run `git checkout branch-name`) we can do:

```
git checkout -b temp-branch-name
```

This will create a new branch `temp-branch-name` which is a copy of our changes but in a new branch

#### Go back to the branch and “hard pull”

We’ll now go back to branch `branch-name` and overwrite our local version with the remote one:

```
git checkout branch-name
```

Followed by `git reset --hard origin/branch-name` as seen in 2.

#### Cherry-pick the commits from temp branch onto the local branch

We’ll now want to switch back to `temp-branch-name` and get the SHAs of the commits we want to apply:

```
git checkout temp-branch-name
```

Followed by

```
git log
```

To see which commits we want to apply (to exit `git log` you can use `q`).

#### Cherry-pick each commit individually

Say we want to apply commits `<commit-sha-1>` and `<commit-sha-2>`.

We’ll switch to the branch that has been reset to the remote version using:

```
git checkout branch-name
```

We’ll then use cherry-pick ([see cherry-pick git docs](https://git-scm.com/docs/git-cherry-pick)) to apply those commits:

```
git cherry-pick <commit-sha1> && git cherry-pick <commit-sha2>
```

#### Cherry-pick a range of commits

If you’ve got a bunch of commits and they’re sequential, you can use the following (for git 1.7.2+)

We’ll make sure to be on the branch that has been reset to the remote version using:

```
git checkout branch-name
```

> For git version 1.7.2+, credit to [**François Marier**](https://fmarier.org/) in “[Cherry-picking a range of git commits](https://feeding.cloud.geek.nz/posts/cherry-picking-range-of-git-commits/)” - [Feeding the Cloud](https://feeding.cloud.geek.nz/)

```
git cherry-pick <first-commit-sha>^..<last-commit-sha>
```

You should now be able to `git push` the local branch to the remote without getting rejected.

[<svg xmlns="http://www.w3.org/2000/svg" style="height:12px;width:auto;position:relative;vertical-align:middle;top:-2px;fill:white" viewbox="0 0 32 32"><title>unsplash-logo</title>
<path d="M10 9V0h12v9H10zm12 5h10v18H0V14h10v9h12v-9z"></path></svg>Alora Griffiths](https://unsplash.com/@aloragriffiths?utm_medium=referral&utm_campaign=photographer-credit&utm_content=creditBadge "Download free do whatever you want high-resolution photos from Alora Griffiths")