I typically use git pull --rebase
if I'm working directly on master (which I try not to do anyway). In the event that I forgot to do a rebase and just did git pull
, is there a way to undo that and make it linear, rather than having a merge? Would doing a rebase at this point be a bad idea (if that would even accomplish anything)?
I know I can put enable rebasing on pulls by default so I don't forget, but this is more of an issue of understanding what to do in this case.
Short answer (already given by @Alex in comments): git reset --hard HEAD^
, but only if there's a merge commit (otherwise you're just backing up one commit from your fast-forward).
Long version with explanation:
git pull
is really just git fetch
followed by git merge
(unless you override with --rebase
, as you note). So you just need to see if you got an actual merge commit or not:
$ git pull
Updating 171ce6f..523bacb
Fast-forward
mp.py | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
create mode 100644 mp.py
In this case there was no merge commit, just a fast-forward, so, no problem—there are no changes to rebase! If you do a git log
you'll see the lack-of-merge-commit, especially if you do the graph-y ones below.
Let's force a merge.
$ git reset --hard HEAD^
HEAD is now at 171ce6f ignore *.log files
[now I'm one behind remotes/origin/master
]
$ echo '# pointless comment' >> selfref.py
$ git add selfref.py
$ git commit -m 'added to force merge'
[master 260e129] added to force merge
1 files changed, 1 insertions(+), 0 deletions(-)
$ git pull
Merge made by recursive.
mp.py | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
create mode 100644 mp.py
We can see that this happened, even if the above text is missing, with:
$ git log --graph --decorate --abbrev-commit --pretty=oneline
* c261bad (HEAD, master) Merge branch 'master' of [ssh url]
|\
| * 523bacb (origin/master, origin/HEAD) add multiprocessing example
* | 260e129 added to force merge
|/
* 171ce6f ignore *.log files
We want to get the local branch name master
to point to (in this case) 260e129 again. Fortunately that's really easy to name:
$ git rev-parse HEAD^
260e1297900b903404c32f3706b0e3139c043ce0
(The other parent of the current, two-parent, merge commit is HEAD^2
.) So:
$ git reset --hard HEAD^
HEAD is now at 260e129 added to force merge
and now we can rebase onto remotes/origin/master
(I'll use the really short name, origin
, to name that):
$ git rebase origin
First, rewinding head to replay your work on top of it...
Applying: added to force merge
Now the graph-y one-line log shows:
$ git log --graph --decorate --abbrev-commit --pretty=oneline
* 4a0b2e2 (HEAD, master) added to force merge
* 523bacb (origin/master, origin/HEAD) add multiprocessing example
* 171ce6f ignore *.log files
From all of this, you should be able to figure out what to do if you run git pull
and it complains that the merge fails. :-)
i guess git reset --hard
back to before the pull and redo the pull is the way
I want to give you some advice which helps to keep history linear. Set the following git configuration for rebasing the branch automatically when you make pull.
$ git config branch.autosetuprebase always
After applying this setting you do not need to type full pull command with --rebase
parameter, just git pull
.
More information you can get in this article http://stevenharman.net/git-pull-with-automatic-rebase
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