Junio C Hamano <[email protected]> writes:
> I can imagine users might want to say "when I am on these small
> number of branches, I want to merge (or rebase), but when I am on
> other, majority of my branches, because they are private, unfinished
> and unpublished work, please stop me from accidentally messing their
> histories with changes from upstream or anywhere else for that
> matter". If that is the issue you are trying to raise, because
> there is no
>
> [pull]
> rebase = fail
> [branch "master"]
> rebase = yes
>
> to force "git pull" to fail by default on any branch while allowing
> it to rebase (or merge, for that matter) only on a few selected
> branches, we fall a bit short.
>
> Which can be solved by adding the above "fail" option, and then
> renaming them to "pull.integrate" and "branch.<name>.integrate" to
> clarify what these variables are about (it is no longer "do you
> rebase or not---if you choose not to rebase, by definition you are
> going to merge", as there is a third choice to "fail"), while
> retaining "pull.rebase" and "branch.<name>.rebase" as a deprecated
> synonym.
The first step of such an enhancement may look like this patch. It
introduces "pull.integrate" and "branch.<name>.integrate" that will
eventually deprecate "*.rebase", but at this step only supports
values "rebase" and "merge" (i.e. no "fail" yet).
The steps after this change would be to
* Enhance addition to t5520 made by 949e0d8e (pull: require choice
between rebase/merge on non-fast-forward pull, 2013-06-27) to
make sure that setting pull.integrate and branch.<name>.integrate
will squelch the safety added by that patch;
* Teach "branch.c" to set "branch.<name>.integrate" either instead
of or in addition to "branch.<name>.rebase", and adjust tests
that expect to see "branch.<name>.rebase" to expect to see that
"branch.<name>.integrate" is set to "rebase";
* Add "fail" to the set of valid values for "*.integrate", and teach
"git pull" honor it; and
* Update builtin/remote.c to show cases where branch.<name>.integrate
is set to "fail" in some different way.
I do not plan to do these follow-up steps myself soonish (hint,
hint).
builtin/remote.c | 12 ++++++++++--
git-pull.sh | 60 +++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 50 insertions(+), 22 deletions(-)
diff --git a/builtin/remote.c b/builtin/remote.c
index 5e54d36..d3b6d0b5 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -274,7 +274,7 @@ static int config_read_branches(const char *key, const char
*value, void *cb)
char *name;
struct string_list_item *item;
struct branch_info *info;
- enum { REMOTE, MERGE, REBASE } type;
+ enum { REMOTE, MERGE, REBASE, INTEGRATE } type;
key += 7;
if (!postfixcmp(key, ".remote")) {
@@ -286,6 +286,9 @@ static int config_read_branches(const char *key, const char
*value, void *cb)
} else if (!postfixcmp(key, ".rebase")) {
name = xstrndup(key, strlen(key) - 7);
type = REBASE;
+ } else if (!postfixcmp(key, ".integrate")) {
+ name = xstrndup(key, strlen(key) - 10);
+ type = INTEGRATE;
} else
return 0;
@@ -309,8 +312,13 @@ static int config_read_branches(const char *key, const
char *value, void *cb)
space = strchr(value, ' ');
}
string_list_append(&info->merge, xstrdup(value));
- } else
+ } else if (type == REBASE) {
info->rebase = git_config_bool(orig_key, value);
+ } else if (type == INTEGRATE) {
+ if (!value)
+ return config_error_nonbool(orig_key);
+ info->rebase = !strcmp(value, "rebase");
+ }
}
return 0;
}
diff --git a/git-pull.sh b/git-pull.sh
index 88c198f..5c557b7 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -45,16 +45,34 @@ merge_args= edit=
curr_branch=$(git symbolic-ref -q HEAD)
curr_branch_short="${curr_branch#refs/heads/}"
-# See if we are configured to rebase by default.
-# The value $rebase is, throughout the main part of the code:
+# See what we are configured to do by default.
+# The value $integration is, throughout the main part of the code:
# (empty) - the user did not have any preference
-# true - the user told us to integrate by rebasing
-# false - the user told us to integrate by merging
-rebase=$(git config --bool branch.$curr_branch_short.rebase)
-if test -z "$rebase"
-then
- rebase=$(git config --bool pull.rebase)
-fi
+# rebase - the user told us to integrate by rebasing
+# merge - the user told us to integrate by merging
+
+integration=
+
+set_integration () {
+ integration=$(git config branch.$curr_branch_short.integrate)
+ test -n "$integration" && return
+
+ case "$(git config --bool branch.$curr_branch_short.rebase)" in
+ true) integration=rebase ;;
+ false) integration=merge ;;
+ esac
+ test -n "$integration" && return
+
+ integration=$(git config pull.integrate)
+ test -n "$integration" && return
+
+ case "$(git config --bool pull.rebase)" in
+ true) integration=rebase ;;
+ false) integration=merge ;;
+ esac
+}
+
+set_integration
dry_run=
while :
@@ -119,11 +137,11 @@ do
merge_args="$merge_args$xx "
;;
-r|--r|--re|--reb|--reba|--rebas|--rebase)
- rebase=true
+ integration=rebase
;;
--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase|\
-m|--m|--me|--mer|--merg|--merge)
- rebase=false
+ integration=merge
;;
--recurse-submodules)
recurse_submodules=--recurse-submodules
@@ -166,7 +184,7 @@ error_on_no_merge_candidates () {
esac
done
- if test true = "$rebase"
+ if test "$integration" = rebase
then
op_type=rebase
op_prep=against
@@ -180,7 +198,8 @@ error_on_no_merge_candidates () {
remote=$(git config "branch.$curr_branch.remote")
if [ $# -gt 1 ]; then
- if [ "$rebase" = true ]; then
+ if test "$integration" = rebase
+ then
printf "There is no candidate for rebasing against "
else
printf "There are no candidates for merging "
@@ -203,7 +222,8 @@ error_on_no_merge_candidates () {
exit 1
}
-test true = "$rebase" && {
+if test "$integration" = rebase
+then
if ! git rev-parse -q --verify HEAD >/dev/null
then
# On an unborn branch
@@ -227,7 +247,7 @@ test true = "$rebase" && {
break
fi
done
-}
+fi
orig_head=$(git rev-parse -q --verify HEAD)
git fetch $verbosity $progress $dry_run $recurse_submodules --update-head-ok
"$@" || exit 1
@@ -269,7 +289,7 @@ case "$merge_head" in
then
die "$(gettext "Cannot merge multiple branches into empty
head")"
fi
- if test true = "$rebase"
+ if test "$integration" = rebase
then
die "$(gettext "Cannot rebase onto multiple branches")"
fi
@@ -279,7 +299,7 @@ case "$merge_head" in
# trigger this check when we will say "fast-forward" or "already
# up-to-date".
merge_head=${merge_head% }
- if test -z "$rebase$no_ff$ff_only${squash#--no-squash}" &&
+ if test -z "$integration$no_ff$ff_only${squash#--no-squash}" &&
test -n "$orig_head" &&
test $# = 0 &&
! git merge-base --is-ancestor "$orig_head" "$merge_head" &&
@@ -311,7 +331,7 @@ then
exit
fi
-if test true = "$rebase"
+if test "$integration" = rebase
then
o=$(git show-branch --merge-base $curr_branch $merge_head $oldremoteref)
if test "$oldremoteref" = "$o"
@@ -321,8 +341,8 @@ then
fi
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
-case "$rebase" in
-true)
+case "$integration" in
+rebase)
eval="git-rebase $diffstat $strategy_args $merge_args $verbosity"
eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}"
;;
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html