I have forked a repo from GitHub and made some commit on my master branch. And the upstream repo's master branch have some commits ahead of mine. So I need sync these commits.
$ git remote -v
origin [email protected]:johnwatsondev/react-navigation.git (fetch)
origin [email protected]:johnwatsondev/react-navigation.git (push)
upstream https://github.com/react-community/react-navigation.git (fetch)
upstream https://github.com/react-community/react-navigation.git (push)
$ git pull --rebase upstream master
From https://github.com/react-community/react-navigation
* branch master -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: Update: add logic for invoking back key pressed listener in CardStack.js and remove default process logic
Applying: Update: only android platform need process physical back key pressed event
$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 6 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean
$ git pull
Merge made by the 'recursive' strategy.
$ git status
On branch master
Your branch is ahead of 'origin/master' by 7 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
I got this ugly commit history in my origin repo's master branch below:

How can I make a elegant OP to sync my origin repo's master branch to upstream's master branch without ugly duplicate commits and the Merge branch *** commit?
(PS: I have make some change in my origin repo's master branch)
As answered in Squash my last X commits together using Git, you can squash the previous n commits into a single commit using
git rebase HEAD~n -i
When you run this command, a text editor will open, and you have to replace the pick in front of all n-1 commits you want to squash, with s. Please note that you have to do a force push after squashing. This way you can merge many commits into one.
There are already lots of answers available on SO regarding how to reset a remote and local history, but I guess your question is more about how to avoid these ugly merge commits during a pull.
In general you don't want to use the default pull behavior when you want to keep a linear history, otherwise you get this ugly merge commits when there are both local and remote changes. You should get into the habit of using git pull -r to use rebase instead of merge strategy during pulls.
Of course you can also can make an alias for that or change the default pull behavior via pull.rebase=true or branch.master.rebase=true if you want to set this in a branch specific way. But git pull -r does some pretty magic stuff sometimes so I'm always wary in changing the default behavior.
The way I like to do it is to do an explicit fetch first via git fetch and only then do a git merge if it's a fast forward merge, or do a git rebase after reviewing the remote changes. This gives way more control. In fact git pull (in its default behavior) is basically a git fetch && git merge which is explains why you get a merge commit when there are new local and remote commits.
Of course you can also work on a local non-remote tracking branch and do explicit merges and rebases on the master branch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With