Вопрос

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.

Это было полезно?

Решение 2

i guess git reset --hard back to before the pull and redo the pull is the way

Другие советы

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 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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top