Skip to contentSkip to conversation

How to pre-empt git pull merge error?

DISCUSSION Pete Forman 6 participants 7 messages Jun 15, 2016

lore
Share & tools
lore
#0 lore raw

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

git fetch
git okay
stop server
backup data
git merge
start server

Here git okay is a place holder for the command I am asking for.

If a file has been changed outside of a commit then git pull fails with the following error.

error: Your local changes to '...' would be overwritten by merge. Aborting. Please, commit your changes or stash them before you can merge.

I would like git okay to perform the pre-merge checks described in git merge and return non-zero status so that the script aborts before the server is stopped.

Possibilities I have looked for and not found include git merge --dry-run. My best line of thought is git status --porcelain | pre-merge-okay. That seems like a lot of work to make a pre-merge-okay that deals with things like benign untracked files.

I have also asked this question on Stack Overflow but received no answers.

http://stackoverflow.com/questions/20221383/

Signature · 1 line
Pete Forman
#1 lore raw
Quoted 11 lines · On Wed, 27 Nov 2013 15:17:27 +0000 Pete Forman <[email protected]> wrote:

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

git fetch
git okay
stop server
backup data
git merge
start server

Quoted 8 lines

Here git okay is a place holder for the command I am asking for.

If a file has been changed outside of a commit then git pull fails with the following error.

error: Your local changes to '...' would be overwritten by merge. Aborting. Please, commit your changes or stash them before you can merge.

What's wrong with "git okay" being

if git merge whatever 2>/dev/null; then
... OK path
else
... "merge failed" path
fi

?

#2 lore raw
Quoted 23 lines · Konstantin Khomoutov
Quoted 11 lines · On Wed, 27 Nov 2013 15:17:27 +0000 Pete Forman <[email protected]> wrote:

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

git fetch
git okay
stop server
backup data
git merge
start server

Quoted 8 lines

Here git okay is a place holder for the command I am asking for.

If a file has been changed outside of a commit then git pull fails with the following error.

error: Your local changes to '...' would be overwritten by merge. Aborting. Please, commit your changes or stash them before you can merge.

Quoted 7 lines

What's wrong with "git okay" being

if git merge whatever 2>/dev/null; then
... OK path
else
... "merge failed" path
fi

The idea seems to be to stop the server before actually doing the merge (and avoid doing so if the merge is bound to fail).

I don't know a simple way to do the pre-merge check without actually doing the merge (other than patching git merge to add a --dry-run option), but you can do a pessimistic check by using the require_work_tree_exists shell function defined in git-sh-setup (copied below, but you can call it from a shell script after doing
. "$(git --exec-path)/git-sh-setup"):

require_clean_work_tree () {
	git rev-parse --verify HEAD >/dev/null || exit 1
	git update-index -q --ignore-submodules --refresh
	err=0

	if ! git diff-files --quiet --ignore-submodules
	then
		echo >&2 "Cannot $1: You have unstaged changes."
		err=1
	fi

	if ! git diff-index --cached --quiet --ignore-submodules HEAD --
	then
		if [ $err = 0 ]
		then
		    echo >&2 "Cannot $1: Your index contains uncommitted changes."
		else
		    echo >&2 "Additionally, your index contains uncommitted changes."
		fi
		err=1
	fi

	if [ $err = 1 ]
	then
		test -n "$2" && echo >&2 "$2"
		exit 1
	fi
}

Additionally, you may want to check that the merge is a fast-forward (hence can't result in merge conflict), e.g. by checking that the current commit is the merge base between itself and the commit to merge (git merge-base HEAD $commit).

Signature · 2 lines
Matthieu Moy
http://www-verimag.imag.fr/~moy/
#3 lore raw
Quoted 14 lines
Quoted 7 lines
Quoted 4 lines · On Wed, 27 Nov 2013 15:17:27 +0000 Pete Forman <[email protected]> wrote:

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

Quoted 7 lines
Quoted 7 lines

git fetch
git okay
stop server
backup data
git merge
start server

Quoted 3 lines

I don't know a simple way to do the pre-merge check without actually doing the merge (other than patching git merge to add a --dry-run option)

Wouldn't that be a nice use-case for git-recursive-merge --index-only ($gmane/236753) ?

#4 lore raw
Quoted 14 lines · Antoine Pelisse
Quoted 14 lines
Quoted 14 lines
Quoted 11 lines · On Wed, 27 Nov 2013 15:17:27 +0000 Pete Forman <[email protected]> wrote:

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

git fetch
git okay
stop server
backup data
git merge
start server

Quoted 6 lines
Quoted 3 lines

I don't know a simple way to do the pre-merge check without actually doing the merge (other than patching git merge to add a --dry-run option)

Wouldn't that be a nice use-case for git-recursive-merge --index-only ($gmane/236753) ?

Possibly, but most of the use-cases for merge --dry-run are better answered by the XY Problem question:

Can you step back and explain what the *underlying* goal is?

The above sounds a lot like a deployment script, and such scripts are almost always better served by using an actual deployment tool, or failing that, by using some form of checkout -f instead, to ensure that they get whatever they are supposed to deploy.

(Using a merge to update is really terrible in the face of non-fast-forward updates, especially when caused by rewriting history to not include some commits.)

Signature · 2 lines
Thomas Rast
[email protected]
#5 lore raw
Quoted 28 lines · Thomas Rast
Quoted 14 lines · Antoine Pelisse
Quoted 14 lines
Quoted 14 lines
Quoted 11 lines · On Wed, 27 Nov 2013 15:17:27 +0000 Pete Forman <[email protected]> wrote:

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

git fetch
git okay
stop server
backup data
git merge
start server

Quoted 6 lines
Quoted 3 lines

I don't know a simple way to do the pre-merge check without actually doing the merge (other than patching git merge to add a --dry-run option)

Wouldn't that be a nice use-case for git-recursive-merge --index-only ($gmane/236753) ?

Possibly, but most of the use-cases for merge --dry-run are better answered by the XY Problem question:

Can you step back and explain what the *underlying* goal is?

Quoted 8 lines

The above sounds a lot like a deployment script, and such scripts are almost always better served by using an actual deployment tool, or failing that, by using some form of checkout -f instead, to ensure that they get whatever they are supposed to deploy.

(Using a merge to update is really terrible in the face of non-fast-forward updates, especially when caused by rewriting history to not include some commits.)

It is a deployment script and updates are fast-forward. There was a problem on a test server where a file had been hacked to investigate an issue. The next deploy failed with the merge error.

There are three approaches, which might all be done with git or an actual deployment tool.

1. test early, bail out if deploy would fail
2. set target to good state before applying the merge 2a. discard changes
2b. stash changes

I intend to use (1). First I will need to clean up the stray files or add more entries into .gitignore.

  test -z "$(git status --porcelain)"
Signature · 2 lines
Pete Forman
http://petef.22web.org/payg.html
#6 lore raw
In reply to Antoine Pelisse
Quoted 14 lines · Antoine Pelisse
Quoted 14 lines
Quoted 14 lines
Quoted 11 lines · On Wed, 27 Nov 2013 15:17:27 +0000 Pete Forman <[email protected]> wrote:

I am looking for a way of detecting up front whether a git pull or git merge would fail. The sort of script I want to perform is to update a server.

git fetch
git okay
stop server
backup data
git merge
start server

Quoted 6 lines
Quoted 3 lines

I don't know a simple way to do the pre-merge check without actually doing the merge (other than patching git merge to add a --dry-run option)

Wouldn't that be a nice use-case for git-recursive-merge --index-only ($gmane/236753) ?

As the original mentions "error: Your local changes to ...", I do not think it would be a good fit.

I have to say that the safest and sanest way may be to:

(1) Commit any such local change(s);

server$ git commit -a

(2) Pull that down to a pre-deploy repository from the "server";

prepare$ git pull ...to grab the "local changes" above...

(3) Merge in whatever the update you want to have on the "server";

prepare$ git merge ...whatever...

(4) and then stop the server, fast-forward to the result of (3), and then restart.

server$ stop server
server$ git pull --ff-only ...the prepared result of (3)... server$ start server