Skip to content

Commit

Permalink
New workflow: push rejected
Browse files Browse the repository at this point in the history
  • Loading branch information
jennybc committed Jan 10, 2019
1 parent 2798bca commit 4fa85ab
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 9 deletions.
1 change: 1 addition & 0 deletions _bookdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ rmd_files: [

"workflows-intro.Rmd",
"workflows-repeated-amend.Rmd",
"workflows-push-rejected.Rmd",
"workflows-pull.Rmd",
"workflows-fork-and-clone.Rmd",
"workflows-upstream-changes-into-fork.Rmd",
Expand Down
13 changes: 6 additions & 7 deletions workflows-intro.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@

Git patterns that come up frequently in real work:

* Commit early and often. [The Repeated Amend](#repeated-amend).
* [Help, I can't push due to upstream changes!](#pull-tricky)
- Pull (rebase? merge?), then push. Yay.
- Pull, oops merge conflicts, abort. Come back later.
- Pull, oops merge conflicts, resolve them. Push.
* [Fork and clone](#fork-and-clone).
* [Get upstream changes for a fork](#upstream-changes).
* Commit early and often. Push less often. [The Repeated Amend](#repeated-amend).
* [Help, my push was rejected!](#push-rejected)
* [Integrating remote and local work](#pull-tricky). Probably so you can push again.
* Burn it all down.
* Time travel:
- "I just need to see the past". Browse and search on GitHub.
Expand All @@ -22,5 +18,8 @@ Git patterns that come up frequently in real work:

Play well with others:

* [Fork and clone](#fork-and-clone).
* [Get upstream changes for a fork](#upstream-changes).
* Disposable fork.
* [Make your repo rewarding to browse on GitHub](#workflows-browsability).
* [Explore and extend a pull request](#pr-extend)
4 changes: 2 additions & 2 deletions workflows-pull.Rmd
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Pull, but you have local work {#pull-tricky}

Problem: You want to pull changes from upstream, but you have done some new work locally since the last time you pulled. This often comes up because what you actually want to do is *push*, but Git won't let you until you first incorporate the upstream changes.
Problem: You want to pull changes from upstream, but you have done some new work locally since the last time you pulled. This often comes up because [what you actually want to do is *push*](#push-rejected), but Git won't let you until you first incorporate the upstream changes.

For the sake of simplicity, assume we're dealing with the `master` branch and the upstream remote is called `origin`.
For the sake of simplicity, assume we're dealing with the `master` branch and the remote is called `origin`.

Recent commit history of `origin/master`:

Expand Down
64 changes: 64 additions & 0 deletions workflows-push-rejected.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Dealing with push rejection {#push-rejected}

Problem: You want to push changes to GitHub, but you are rejected like so:

``` bash
$ git push
To https://github.com/YOU/REPO.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'https://github.com/YOU/REPO.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
```

This means that your local Git history and that on the GitHub remote are not compatible, i.e. they have diverged.

In the abstract, this is the state on GitHub:

```
A -- B -- C (on GitHub)
```

And this is your local state:

```
A -- B -- D (what you have)
```

You can't cause some sort of merge to happen to the GitHub copy when you push.

Instead, you've got pull the commit `C` and somehow integrate it into your `D`-containing history. Then you will be able to push again.

This is covered in the workflow [Pull, but you have local work](#pull-tricky).

## She who pushes first wins!

You may have noticed that you -- the author of `D` -- is faffing around with Git more than the person who committed and pushed `C`, i.e. your collaborator.

There is a lesson to be learned here!

If you had pushed `D` first, you'd be relaxing and they'd be figuring out how to integrate `C` into their history in order to push. So push your work often. Don't go dark and work "offline" for long stretches of time.

Obviously, you should push work to `master` because it's "ready" to share (or at least "ready enough"), not to avoid Git merges.

There is a truy legitimate point here: It is better for the overall health of a project to be committing, pushing, and integrating more often, not less. This does not eliminate the need to integrate different lines of work, but it makes each integration smaller, less burdensome, and less prone to error.

## Stay in touch

Another take away is this: the sooner you know about `C`, the better. Pull (or fetch) often.

Let's think about your commit `D`. Maybe it was built up over a couple of days via the [Repeated Amend pattern](#repeated-amend). Maybe `C` was sitting there on GitHub the whole time or appeared very early in your process.

Consider that it might be easier to integrate `C` into your work `D` sooner rather than later. Sometimes this is not true, but more often it is.

In general, it pays off to be proactively aware of what others are doing (e.g. to pull or fetch often) than to always be in reactive mode, learning about your collaborator's work only when your push is rejected.

## Use branches

Finally, your early experiences collaborating with others and yourself in `master` will give you a visceral understanding of why most Git users eventually start to use [branches](#git-branches).

Branches afford explicit workflows for integrating different lines of work on your own terms. This is much nicer than trying to do a tricky merge or rebase in a frustrated panic, because you need to push your work to GitHub at the end of the day.

0 comments on commit 4fa85ab

Please sign in to comment.