Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
706 views
in Technique[技术] by (71.8m points)

How to make Git honor a cancelled merge that was not asked for?

I've run into this situation about 3 or 4 times now. On occasion, Git will want to perform a merge. It happens in response to a git commit <filename> -m <message> followed by a git push.

I know a merge is about to occur because Git spins up the editor for the message. So I perform a CTRL + C in an attempt to stop it.

I don't really care why or what got me into the state. When things have to be merged, I just want to stop. I do not want it to occur because it pollutes the check-ins, pollutes the history and sometimes adds stuff that's not ready.

However, I see that Git still performs the merge. Confer: Merge branch 'master' of https://github.com/weidai11/cryptopp.

Once I CTRL + C, the merge should not proceed. How to make Git honor a cancelled merge that was not asked for?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

git push should normally fail if there are any new commits on the remote, that you don't have on your local branch yet.

In order to push, you cannot be missing any commits that the server has.

In the example you posted, you seem to have made the commits d091b80 and 217cb1f on two different machines or two different local copies.

When you were trying to push 217cb1f, the server already had d091b80, while you didn't have it in your local branch.

Before git can push to the server, you will need to pull that other commit from the server.

Usually that is something, that you would do manually. For some reason it seems like your git push is somehow invoking a git pull.

While I couldn't find a specific option to enable this sort of behavior (and wouldn't suggest doing so either), I can see that some people would want git to behave this way.
If you are using another persons config files for git or for your shell, I would have a look if there is anything that might cause this weird behavior.

So how does the merge commit generally come about? Set aside the weird behavior of the push command and assume you had manually done a pull:

Git pull causes an unexpected merge commit

Git pull is doing two things:

  • It fetches the remote
  • It merges the remote branch into your local branch

If there you have no new commits on your local machine, then you have a linear history and changes from the server will be included by fast-forwarding. This means that your local branch will simply be set to the same revision as the remote branch (visualise just having to walk down a little further on a single road).

Imagine you have made a commit on your local branch, while a colleague (or yourself on a different machine) has pushed another change to the remote branch on the server:
The two branches have now wandered into separate ways (visualise one road splitting into two here). When git pull tries to merge them together it will need to make a merge commit (visualise two roads merging into one).

Alternatively you could do git pull --rebase or set the corresponding setting in your git config. This will tell git to apply your local changes to the "end of the road" of the server.
Note though, that a rebasing makes conflict resolution much harder and is generally more complicated than merges.


Pushing as early as possible minimises branch diversion. If you haven't made any new local commits yet, it is also a good idea to pull changes from the server before you are making a commit. That way, you are preventing your branches from diverting.

A good way to do this is:

git stash       # This saves your uncommitted changes away as a draft
git pull        # Gets new commits from the remote
git stash pop   # Restores your uncommitted changes

Abort a merge, while already editing the commit message

  1. Empty the commit message in your editors buffer, save and exit.
    Any comments (prefixed with #) can stay as they are removed by git before evaluating (though this behaviour can be changed in the config).
    If you are vim user, I believe dG:x to be the fastest way to do this.
  2. Run git merge --abort
    This will make git try to restore the pre-merge state of your working copy.
    This command is available in git 1.7.4 or higher. For more info have a look at the man entry for git-merge.

Why Ctrl+C does not do what one might expect

Simply pressing Ctrl+C will (in most, if not all cases) not do what you expect. When git launches a command line editor (such as vim, emacs or nano) that editor becomes the active/current process of that shell.

Press Ctrl+C will send a SIGINT signal to the current process. Meaning, sending SIGINT to your editor and not to git.

If you were to use an editor, that fails (quits and returns an exit code other than 0) when receiving that signal, that might (though I have not tested it) abort the commit.
As will an editor, that saves an empty buffer and quits.
If you configure git to launch a GUI editor it will remain the frontmost process and a SIGINT should still abort the commit.

Note, that in all three cases you will likely have the changes from the other branch in your working copy and you will need to clean them up (see step 2).


For me personally (and a lot of extensive git users), this behaviour is what I would want from git. If you see that differently, you could file a bug report or feature request here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...