Skip to content

Instantly share code, notes, and snippets.

@OleksiyRudenko
Last active September 19, 2022 21:15
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OleksiyRudenko/8b3ddb664308de0634b53c525e551d8b to your computer and use it in GitHub Desktop.
Save OleksiyRudenko/8b3ddb664308de0634b53c525e551d8b to your computer and use it in GitHub Desktop.
Fixing contribution issues

Re-sync fork with upstream

Often beginner contributors face on their contribution path an issue when a PR contains commits the contributor didn't intend to include in the PR.

Table of Contents

A. thiS happens

Let's assume that you have

  1. some repo (hereinafter usptream repo) forked to your account (hereinafter origin repo)
  2. cloned locally (hereinafter local repo)
  3. added some changes
  4. committed those to local master
  5. pushed changes to origin/master

Now you can open a PR, and you do. The PR gets reviewed, conflicts (if any) resolved, and things get merged into upstream. Things went smoothly and everybody is happy.

Now you want to contribute even more. So, you do the following:

  1. add changes
  2. commit to local master
  3. push to origin/master
  4. open a new PR

Oh, craps! PR now lists not only intended changes to add but also commits that's been already merged into master before. And upstream maintainers ask you to get rid off those unnecessary commits.

Ok. You've heard before that you have to use dedicated feature branches. So you trying to fix things you've done the following:

  1. close the bad PR
  2. undo the latest commits so master is exactly at the commit as it was at upon successful PR
  3. checkout a feature branch (e.g. feature)
  4. add changes
  5. commit to local feature
  6. push to origin/feature
  7. open a new PR

Oh, craps! The only difference now is that PR mentions feature branch instead of master, it contains exactly same commits as the last time.

You're in despair. But let's fix it and learn not to step on a rake any more.

Why thiS happened?

Need to understand why it happened.

Let's assume that when you forked the upstream its history was as follows:

* c4ebbab (origin/master, origin/HEAD, master) Add something else
* 0bb232d Add some code
* c040c31 Initial commit

So you add something and now you've got:

* 323043c Add Important contribution (origin/master, origin/HEAD, master)
* c4ebbab Add something else
* 0bb232d Add some code
* c040c31 Initial commit

Push, open PR, get approved and merged, done.

Now you contribute more which results in:

* 5446203 Add Next contribution (origin/master, origin/HEAD, master)
* 323043c Add Important contribution
* c4ebbab Add something else
* 0bb232d Add some code
* c040c31 Initial commit

Push, open PR, and... craps! Your PR lists commits 5446203 and 323043c. Why that?

If you take a look at upstream history you will note that your commit saying Add Important contribution has different hash (this happened beacuse maintainers rebased your commit(s) onto upstream's master and rebase always creates a new commit even if the content wasn't changed). So PR manager finds the most recent commit that both usptream and origin share and adds the remaining commits to the PR's scope. That's it.

Honey, I fixed it

A. Reset master

  1. git branch backup-feature - to keep track of your current feature branch if any
  2. git checkout master
  3. git branch backup-master - to keep track of your master
  4. identify the most recent commit that both usptream and origin share (c4ebbab in our example)
  5. git checkout c4ebbab - move to the shared commit
  6. git branch -f master - move master pointer forcedly
  7. git checkout master
  8. git push -f - update origin forcedly

The force actions above are actually bad practice. Never use those on shared repos unless you clearly understand consequences and your collaborators are aware of these actions.

B. Get synced with upstream

  1. git remote add upstream upstream-url.git - add a remote
  2. git pull upstream master - update your local from usptream
  3. git push - update your origin from local

C. Add/pick your changes

  1. git branch -f feature-branch - create or forcedly move a feature branch pointer
  2. git checkout feature-branch - switch to the feature branch
  3. add changes and git commit -am "..." or git cherry-pick 5446203 - pick commits as appropriate, where 5446203 is a commit containing changes you want to re-apply
  4. git push -f - push feature branch (forcedly for the case you re-used branch name)

Now you are set to open a PR and live normal contributor's life further.

D. Clean-up

You do not need your back up branches, you also do not need feature branches once changes get merged into upstream.

Just remove backup-master, backup-feature and feature branches with git branch -d <branch-name> and git push origin --delete <branch-name> (from remote as well).

Need your changes back? Just sync with upstream/master to have those back. The concise guide referred to below covers the complete contribution workflow.

Was this helpful? Please, give this gist a ⭐.

No, it didn't help

This mean you need to find even earlier (before irreversible entanglements you managed to bring in) shared commit to start over with.

How to avoid?

The flight rule No.1 is not to commit to fork's (origin) master. Fork's master should be updated from upstream only.

For more details on better contribution workflow read the Contributing to a 3rd party repo for beginners guide

Useful resources

Credits

Thanks to Karasb888 for beta-testing and detailed feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment