Merge branch 'mm/conflict-advice'
* mm/conflict-advice: Be more user-friendly when refusing to do something because of conflict. Conflicts: Documentation/config.txt advice.c advice.h
This commit is contained in:
commit
71b3ef11fa
@ -130,6 +130,10 @@ advice.*::
|
|||||||
Advice shown when linkgit:git-merge[1] refuses to
|
Advice shown when linkgit:git-merge[1] refuses to
|
||||||
merge to avoid overwritting local changes.
|
merge to avoid overwritting local changes.
|
||||||
Default: true.
|
Default: true.
|
||||||
|
resolveConflict::
|
||||||
|
Advices shown by various commands when conflicts
|
||||||
|
prevent the operation from being performed.
|
||||||
|
Default: true.
|
||||||
implicitIdentity::
|
implicitIdentity::
|
||||||
Advice on how to set your identity configuration when
|
Advice on how to set your identity configuration when
|
||||||
your information is guessed from the system username and
|
your information is guessed from the system username and
|
||||||
|
16
advice.c
16
advice.c
@ -3,6 +3,7 @@
|
|||||||
int advice_push_nonfastforward = 1;
|
int advice_push_nonfastforward = 1;
|
||||||
int advice_status_hints = 1;
|
int advice_status_hints = 1;
|
||||||
int advice_commit_before_merge = 1;
|
int advice_commit_before_merge = 1;
|
||||||
|
int advice_resolve_conflict = 1;
|
||||||
int advice_implicit_identity = 1;
|
int advice_implicit_identity = 1;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
@ -12,6 +13,7 @@ static struct {
|
|||||||
{ "pushnonfastforward", &advice_push_nonfastforward },
|
{ "pushnonfastforward", &advice_push_nonfastforward },
|
||||||
{ "statushints", &advice_status_hints },
|
{ "statushints", &advice_status_hints },
|
||||||
{ "commitbeforemerge", &advice_commit_before_merge },
|
{ "commitbeforemerge", &advice_commit_before_merge },
|
||||||
|
{ "resolveconflict", &advice_resolve_conflict },
|
||||||
{ "implicitidentity", &advice_implicit_identity },
|
{ "implicitidentity", &advice_implicit_identity },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -29,3 +31,17 @@ int git_default_advice_config(const char *var, const char *value)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NORETURN die_resolve_conflict(const char *me)
|
||||||
|
{
|
||||||
|
if (advice_resolve_conflict)
|
||||||
|
/*
|
||||||
|
* Message used both when 'git commit' fails and when
|
||||||
|
* other commands doing a merge do.
|
||||||
|
*/
|
||||||
|
die("'%s' is not possible because you have unmerged files.\n"
|
||||||
|
"Please, fix them up in the work tree, and then use 'git add/rm <file>' as\n"
|
||||||
|
"appropriate to mark resolution and make a commit, or use 'git commit -a'.", me);
|
||||||
|
else
|
||||||
|
die("'%s' is not possible because you have unmerged files.", me);
|
||||||
|
}
|
||||||
|
5
advice.h
5
advice.h
@ -1,11 +1,16 @@
|
|||||||
#ifndef ADVICE_H
|
#ifndef ADVICE_H
|
||||||
#define ADVICE_H
|
#define ADVICE_H
|
||||||
|
|
||||||
|
#include "git-compat-util.h"
|
||||||
|
|
||||||
extern int advice_push_nonfastforward;
|
extern int advice_push_nonfastforward;
|
||||||
extern int advice_status_hints;
|
extern int advice_status_hints;
|
||||||
extern int advice_commit_before_merge;
|
extern int advice_commit_before_merge;
|
||||||
|
extern int advice_resolve_conflict;
|
||||||
extern int advice_implicit_identity;
|
extern int advice_implicit_identity;
|
||||||
|
|
||||||
int git_default_advice_config(const char *var, const char *value);
|
int git_default_advice_config(const char *var, const char *value);
|
||||||
|
|
||||||
|
extern void NORETURN die_resolve_conflict(const char *me);
|
||||||
|
|
||||||
#endif /* ADVICE_H */
|
#endif /* ADVICE_H */
|
||||||
|
@ -258,6 +258,16 @@ static void create_base_index(void)
|
|||||||
exit(128); /* We've already reported the error, finish dying */
|
exit(128); /* We've already reported the error, finish dying */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void refresh_cache_or_die(int refresh_flags)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* refresh_flags contains REFRESH_QUIET, so the only errors
|
||||||
|
* are for unmerged entries.
|
||||||
|
*/
|
||||||
|
if (refresh_cache(refresh_flags | REFRESH_IN_PORCELAIN))
|
||||||
|
die_resolve_conflict("commit");
|
||||||
|
}
|
||||||
|
|
||||||
static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
|
static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
@ -297,7 +307,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int
|
|||||||
if (all || (also && pathspec && *pathspec)) {
|
if (all || (also && pathspec && *pathspec)) {
|
||||||
int fd = hold_locked_index(&index_lock, 1);
|
int fd = hold_locked_index(&index_lock, 1);
|
||||||
add_files_to_cache(also ? prefix : NULL, pathspec, 0);
|
add_files_to_cache(also ? prefix : NULL, pathspec, 0);
|
||||||
refresh_cache(refresh_flags);
|
refresh_cache_or_die(refresh_flags);
|
||||||
if (write_cache(fd, active_cache, active_nr) ||
|
if (write_cache(fd, active_cache, active_nr) ||
|
||||||
close_lock_file(&index_lock))
|
close_lock_file(&index_lock))
|
||||||
die("unable to write new_index file");
|
die("unable to write new_index file");
|
||||||
@ -316,7 +326,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int
|
|||||||
*/
|
*/
|
||||||
if (!pathspec || !*pathspec) {
|
if (!pathspec || !*pathspec) {
|
||||||
fd = hold_locked_index(&index_lock, 1);
|
fd = hold_locked_index(&index_lock, 1);
|
||||||
refresh_cache(refresh_flags);
|
refresh_cache_or_die(refresh_flags);
|
||||||
if (write_cache(fd, active_cache, active_nr) ||
|
if (write_cache(fd, active_cache, active_nr) ||
|
||||||
commit_locked_index(&index_lock))
|
commit_locked_index(&index_lock))
|
||||||
die("unable to write new_index file");
|
die("unable to write new_index file");
|
||||||
|
@ -849,11 +849,20 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
|||||||
const char *best_strategy = NULL, *wt_strategy = NULL;
|
const char *best_strategy = NULL, *wt_strategy = NULL;
|
||||||
struct commit_list **remotes = &remoteheads;
|
struct commit_list **remotes = &remoteheads;
|
||||||
|
|
||||||
if (file_exists(git_path("MERGE_HEAD")))
|
if (read_cache_unmerged()) {
|
||||||
die("You have not concluded your merge. (MERGE_HEAD exists)");
|
die_resolve_conflict("merge");
|
||||||
if (read_cache_unmerged())
|
}
|
||||||
die("You are in the middle of a conflicted merge."
|
if (file_exists(git_path("MERGE_HEAD"))) {
|
||||||
" (index unmerged)");
|
/*
|
||||||
|
* There is no unmerged entry, don't advise 'git
|
||||||
|
* add/rm <file>', just 'git commit'.
|
||||||
|
*/
|
||||||
|
if (advice_resolve_conflict)
|
||||||
|
die("You have not concluded your merge (MERGE_HEAD exists).\n"
|
||||||
|
"Please, commit your changes before you can merge.");
|
||||||
|
else
|
||||||
|
die("You have not concluded your merge (MERGE_HEAD exists).");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if we are _not_ on a detached HEAD, i.e. if there is a
|
* Check if we are _not_ on a detached HEAD, i.e. if there is a
|
||||||
|
@ -235,6 +235,19 @@ static struct tree *empty_tree(void)
|
|||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NORETURN void die_dirty_index(const char *me)
|
||||||
|
{
|
||||||
|
if (read_cache_unmerged()) {
|
||||||
|
die_resolve_conflict(me);
|
||||||
|
} else {
|
||||||
|
if (advice_commit_before_merge)
|
||||||
|
die("Your local changes would be overwritten by %s.\n"
|
||||||
|
"Please, commit your changes or stash them to proceed.", me);
|
||||||
|
else
|
||||||
|
die("Your local changes would be overwritten by %s.\n", me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int revert_or_cherry_pick(int argc, const char **argv)
|
static int revert_or_cherry_pick(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
unsigned char head[20];
|
unsigned char head[20];
|
||||||
@ -271,7 +284,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
|||||||
if (get_sha1("HEAD", head))
|
if (get_sha1("HEAD", head))
|
||||||
die ("You do not have a valid HEAD");
|
die ("You do not have a valid HEAD");
|
||||||
if (index_differs_from("HEAD", 0))
|
if (index_differs_from("HEAD", 0))
|
||||||
die ("Dirty index: cannot %s", me);
|
die_dirty_index(me);
|
||||||
}
|
}
|
||||||
discard_cache();
|
discard_cache();
|
||||||
|
|
||||||
|
25
git-pull.sh
25
git-pull.sh
@ -13,8 +13,29 @@ set_reflog_action "pull $*"
|
|||||||
require_work_tree
|
require_work_tree
|
||||||
cd_to_toplevel
|
cd_to_toplevel
|
||||||
|
|
||||||
test -z "$(git ls-files -u)" ||
|
|
||||||
die "You are in the middle of a conflicted merge."
|
die_conflict () {
|
||||||
|
git diff-index --cached --name-status -r --ignore-submodules HEAD --
|
||||||
|
if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
|
||||||
|
die "Pull is not possible because you have unmerged files.
|
||||||
|
Please, fix them up in the work tree, and then use 'git add/rm <file>'
|
||||||
|
as appropriate to mark resolution, or use 'git commit -a'."
|
||||||
|
else
|
||||||
|
die "Pull is not possible because you have unmerged files."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
die_merge () {
|
||||||
|
if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
|
||||||
|
die "You have not concluded your merge (MERGE_HEAD exists).
|
||||||
|
Please, commit your changes before you can merge."
|
||||||
|
else
|
||||||
|
die "You have not concluded your merge (MERGE_HEAD exists)."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
test -z "$(git ls-files -u)" || die_conflict
|
||||||
|
test -f "$GIT_DIR/MERGE_HEAD" && die_merge
|
||||||
|
|
||||||
strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
|
strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
|
||||||
log_arg= verbosity=
|
log_arg= verbosity=
|
||||||
|
@ -276,11 +276,13 @@ test_expect_success 'fail if the index has unresolved entries' '
|
|||||||
|
|
||||||
test_must_fail git merge "$c5" &&
|
test_must_fail git merge "$c5" &&
|
||||||
test_must_fail git merge "$c5" 2> out &&
|
test_must_fail git merge "$c5" 2> out &&
|
||||||
|
grep "not possible because you have unmerged files" out &&
|
||||||
|
git add -u &&
|
||||||
|
test_must_fail git merge "$c5" 2> out &&
|
||||||
grep "You have not concluded your merge" out &&
|
grep "You have not concluded your merge" out &&
|
||||||
rm -f .git/MERGE_HEAD &&
|
rm -f .git/MERGE_HEAD &&
|
||||||
test_must_fail git merge "$c5" 2> out &&
|
test_must_fail git merge "$c5" 2> out &&
|
||||||
grep "You are in the middle of a conflicted merge" out
|
grep "Your local changes to .* would be overwritten by merge." out
|
||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'merge-recursive remove conflict' '
|
test_expect_success 'merge-recursive remove conflict' '
|
||||||
|
@ -66,7 +66,7 @@ test_expect_success 'revert forbidden on dirty working tree' '
|
|||||||
echo content >extra_file &&
|
echo content >extra_file &&
|
||||||
git add extra_file &&
|
git add extra_file &&
|
||||||
test_must_fail git revert HEAD 2>errors &&
|
test_must_fail git revert HEAD 2>errors &&
|
||||||
grep "Dirty index" errors
|
grep "Your local changes would be overwritten by " errors
|
||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user