I've implemented classic OSS maintainer/contributor git workflow for a company project on github, however one edge case produces some weird results that I'm not sure how to get around.
Lets say there is a typical project that I forked and added upstream remote to keep it up to date.
git clone git@github.com:kozhevnikov/<project>.git
git remote add upstream git@github.com:<company>/<project>.git
For the purposes of this example this fork is behind by a few commits.
git reset --hard HEAD~5 && git push --force
I work on this fork and push some commits, before pushing my last commit and creating a pull request I update my fork's clone to make sure there are no conflicts.
touch foo && git add foo && git commit -m foo && git push
touch bar && git add bar && git commit -m bar
git pull --rebase upstream master
From github.com:<company>/<project>
* branch master -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: foo
Applying: bar
Now, when I try to push to my fork I get rejected.
git push
To git@github.com:kozhevnikov/<project>.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:kozhevnikov/<project>.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again. See the
'Note about fast-forwards' section of 'git push --help' for details.
What should I do next? All I want is for the pull request to contain foo and bar commits, however...
When I pull
, pull request contains duplicate foo commits as well as extra merge one.
git pull
Merge made by the 'recursive' strategy.
git push
On github pull request looks like this.
Showing 4 unique commits by 1 author.
12345
kozhevnikov foo 4 minutes ago
67890
kozhevnikov foo 4 minutes ago
abcde
kozhevnikov bar 2 minutes ago
fghij
kozhevnikov Merge branch 'master' of github.com:kozhevnikov/<project> just now
When I git pull --rebase
instead of pull
, at best it'll include other people's commits into my pull request (those from reset), and at worst it gives me merge conflicts.
When I git push --force
without any pull
or --rebase
it works perfectly, however I'm very uneasy in saying to everyone use the force or making it part of standard workflow as I can imagine few people or a small subteam collaborating on a single fork and stepping on each other's toes with forced push.
Any ideas? What am I missing?