git-commit-vandalism/builtin/pull.c

1010 lines
29 KiB
C
Raw Normal View History

/*
* Builtin "git pull"
*
* Based on git-pull.sh by Junio C Hamano
*
* Fetch one or more remote refs and merge it/them into the current HEAD.
*/
#define USE_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
#include "config.h"
#include "builtin.h"
#include "parse-options.h"
#include "exec-cmd.h"
#include "run-command.h"
2015-06-18 12:54:02 +02:00
#include "sha1-array.h"
#include "remote.h"
#include "dir.h"
#include "refs.h"
#include "refspec.h"
#include "revision.h"
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
#include "submodule.h"
#include "submodule-config.h"
#include "tempfile.h"
#include "lockfile.h"
#include "wt-status.h"
#include "commit-reach.h"
#include "sequencer.h"
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
enum rebase_type {
REBASE_INVALID = -1,
REBASE_FALSE = 0,
REBASE_TRUE,
REBASE_PRESERVE,
REBASE_MERGES,
REBASE_INTERACTIVE
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
};
/**
* Parses the value of --rebase. If value is a false value, returns
* REBASE_FALSE. If value is a true value, returns REBASE_TRUE. If value is
* "merges", returns REBASE_MERGES. If value is "preserve", returns
* REBASE_PRESERVE. If value is a invalid value, dies with a fatal error if
* fatal is true, otherwise returns REBASE_INVALID.
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
*/
static enum rebase_type parse_config_rebase(const char *key, const char *value,
int fatal)
{
int v = git_parse_maybe_bool(value);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (!v)
return REBASE_FALSE;
else if (v > 0)
return REBASE_TRUE;
else if (!strcmp(value, "preserve") || !strcmp(value, "p"))
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
return REBASE_PRESERVE;
else if (!strcmp(value, "merges") || !strcmp(value, "m"))
return REBASE_MERGES;
else if (!strcmp(value, "interactive") || !strcmp(value, "i"))
return REBASE_INTERACTIVE;
/*
* Please update _git_config() in git-completion.bash when you
* add new rebase modes.
*/
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (fatal)
die(_("Invalid value for %s: %s"), key, value);
else
error(_("Invalid value for %s: %s"), key, value);
return REBASE_INVALID;
}
/**
* Callback for --rebase, which parses arg with parse_config_rebase().
*/
static int parse_opt_rebase(const struct option *opt, const char *arg, int unset)
{
enum rebase_type *value = opt->value;
if (arg)
*value = parse_config_rebase("--rebase", arg, 0);
else
*value = unset ? REBASE_FALSE : REBASE_TRUE;
return *value == REBASE_INVALID ? -1 : 0;
}
static const char * const pull_usage[] = {
N_("git pull [<options>] [<repository> [<refspec>...]]"),
NULL
};
/* Shared options */
static int opt_verbosity;
static char *opt_progress;
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
/* Options passed to git-merge or git-rebase */
static enum rebase_type opt_rebase = -1;
static char *opt_diffstat;
static char *opt_log;
static char *opt_signoff;
static char *opt_squash;
static char *opt_commit;
static char *opt_edit;
static char *cleanup_arg;
static char *opt_ff;
static char *opt_verify_signatures;
static int opt_autostash = -1;
static int config_autostash;
static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
static char *opt_gpg_sign;
static int opt_allow_unrelated_histories;
/* Options passed to git-fetch */
static char *opt_all;
static char *opt_append;
static char *opt_upload_pack;
static int opt_force;
static char *opt_tags;
static char *opt_prune;
static char *max_children;
static int opt_dry_run;
static char *opt_keep;
static char *opt_depth;
static char *opt_unshallow;
static char *opt_update_shallow;
static char *opt_refmap;
static char *opt_ipv4;
static char *opt_ipv6;
static struct option pull_options[] = {
/* Shared options */
OPT__VERBOSITY(&opt_verbosity),
OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
N_("force progress reporting"),
PARSE_OPT_NOARG),
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
{ OPTION_CALLBACK, 0, "recurse-submodules",
&recurse_submodules, N_("on-demand"),
N_("control for recursive fetching of submodules"),
PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules },
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
/* Options passed to git-merge or git-rebase */
OPT_GROUP(N_("Options related to merging")),
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
{ OPTION_CALLBACK, 'r', "rebase", &opt_rebase,
"(false|true|merges|preserve|interactive)",
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
N_("incorporate changes by rebasing rather than merging"),
PARSE_OPT_OPTARG, parse_opt_rebase },
OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
N_("do not show a diffstat at the end of the merge"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG),
OPT_PASSTHRU(0, "stat", &opt_diffstat, NULL,
N_("show a diffstat at the end of the merge"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL,
N_("(synonym to --stat)"),
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN),
OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
N_("add (at most <n>) entries from shortlog to merge commit message"),
PARSE_OPT_OPTARG),
OPT_PASSTHRU(0, "signoff", &opt_signoff, NULL,
N_("add Signed-off-by:"),
PARSE_OPT_OPTARG),
OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
N_("create a single commit instead of doing a merge"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "commit", &opt_commit, NULL,
N_("perform a commit if the merge succeeds (default)"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
N_("edit message before committing"),
PARSE_OPT_NOARG),
OPT_CLEANUP(&cleanup_arg),
OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
N_("allow fast-forward"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "ff-only", &opt_ff, NULL,
N_("abort if fast-forward is not possible"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG),
OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL,
N_("verify that the named commit has a valid GPG signature"),
PARSE_OPT_NOARG),
OPT_BOOL(0, "autostash", &opt_autostash,
N_("automatically stash/stash pop before and after rebase")),
OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"),
N_("merge strategy to use"),
0),
OPT_PASSTHRU_ARGV('X', "strategy-option", &opt_strategy_opts,
N_("option=value"),
N_("option for selected merge strategy"),
0),
OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"),
N_("GPG sign commit"),
PARSE_OPT_OPTARG),
OPT_SET_INT(0, "allow-unrelated-histories",
&opt_allow_unrelated_histories,
N_("allow merging unrelated histories"), 1),
/* Options passed to git-fetch */
OPT_GROUP(N_("Options related to fetching")),
OPT_PASSTHRU(0, "all", &opt_all, NULL,
N_("fetch from all remotes"),
PARSE_OPT_NOARG),
OPT_PASSTHRU('a', "append", &opt_append, NULL,
N_("append to .git/FETCH_HEAD instead of overwriting"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "upload-pack", &opt_upload_pack, N_("path"),
N_("path to upload pack on remote end"),
0),
OPT__FORCE(&opt_force, N_("force overwrite of local branch"), 0),
OPT_PASSTHRU('t', "tags", &opt_tags, NULL,
N_("fetch all tags and associated objects"),
PARSE_OPT_NOARG),
OPT_PASSTHRU('p', "prune", &opt_prune, NULL,
N_("prune remote-tracking branches no longer on remote"),
PARSE_OPT_NOARG),
OPT_PASSTHRU('j', "jobs", &max_children, N_("n"),
N_("number of submodules pulled in parallel"),
PARSE_OPT_OPTARG),
OPT_BOOL(0, "dry-run", &opt_dry_run,
N_("dry run")),
OPT_PASSTHRU('k', "keep", &opt_keep, NULL,
N_("keep downloaded pack"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "depth", &opt_depth, N_("depth"),
N_("deepen history of shallow clone"),
0),
OPT_PASSTHRU(0, "unshallow", &opt_unshallow, NULL,
N_("convert to a complete repository"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "update-shallow", &opt_update_shallow, NULL,
N_("accept refs that update .git/shallow"),
PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "refmap", &opt_refmap, N_("refmap"),
N_("specify fetch refmap"),
PARSE_OPT_NONEG),
OPT_PASSTHRU('4', "ipv4", &opt_ipv4, NULL,
N_("use IPv4 addresses only"),
PARSE_OPT_NOARG),
OPT_PASSTHRU('6', "ipv6", &opt_ipv6, NULL,
N_("use IPv6 addresses only"),
PARSE_OPT_NOARG),
OPT_END()
};
/**
* Pushes "-q" or "-v" switches into arr to match the opt_verbosity level.
*/
static void argv_push_verbosity(struct argv_array *arr)
{
int verbosity;
for (verbosity = opt_verbosity; verbosity > 0; verbosity--)
argv_array_push(arr, "-v");
for (verbosity = opt_verbosity; verbosity < 0; verbosity++)
argv_array_push(arr, "-q");
}
/**
* Pushes "-f" switches into arr to match the opt_force level.
*/
static void argv_push_force(struct argv_array *arr)
{
int force = opt_force;
while (force-- > 0)
argv_array_push(arr, "-f");
}
/**
* Sets the GIT_REFLOG_ACTION environment variable to the concatenation of argv
*/
static void set_reflog_message(int argc, const char **argv)
{
int i;
struct strbuf msg = STRBUF_INIT;
for (i = 0; i < argc; i++) {
if (i)
strbuf_addch(&msg, ' ');
strbuf_addstr(&msg, argv[i]);
}
setenv("GIT_REFLOG_ACTION", msg.buf, 0);
strbuf_release(&msg);
}
/**
* If pull.ff is unset, returns NULL. If pull.ff is "true", returns "--ff". If
* pull.ff is "false", returns "--no-ff". If pull.ff is "only", returns
* "--ff-only". Otherwise, if pull.ff is set to an invalid value, die with an
* error.
*/
static const char *config_get_ff(void)
{
const char *value;
if (git_config_get_value("pull.ff", &value))
return NULL;
switch (git_parse_maybe_bool(value)) {
case 0:
return "--no-ff";
case 1:
return "--ff";
}
if (!strcmp(value, "only"))
return "--ff-only";
die(_("Invalid value for pull.ff: %s"), value);
}
/**
* Returns the default configured value for --rebase. It first looks for the
* value of "branch.$curr_branch.rebase", where $curr_branch is the current
* branch, and if HEAD is detached or the configuration key does not exist,
* looks for the value of "pull.rebase". If both configuration keys do not
* exist, returns REBASE_FALSE.
*/
static enum rebase_type config_get_rebase(void)
{
struct branch *curr_branch = branch_get("HEAD");
const char *value;
if (curr_branch) {
char *key = xstrfmt("branch.%s.rebase", curr_branch->name);
if (!git_config_get_value(key, &value)) {
enum rebase_type ret = parse_config_rebase(key, value, 1);
free(key);
return ret;
}
free(key);
}
if (!git_config_get_value("pull.rebase", &value))
return parse_config_rebase("pull.rebase", value, 1);
return REBASE_FALSE;
}
/**
* Read config variables.
*/
static int git_pull_config(const char *var, const char *value, void *cb)
{
if (!strcmp(var, "rebase.autostash")) {
config_autostash = git_config_bool(var, value);
return 0;
} else if (!strcmp(var, "submodule.recurse")) {
recurse_submodules = git_config_bool(var, value) ?
RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
return 0;
}
return git_default_config(var, value, cb);
}
2015-06-18 12:54:02 +02:00
/**
* Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
* into merge_heads.
*/
static void get_merge_heads(struct oid_array *merge_heads)
2015-06-18 12:54:02 +02:00
{
const char *filename = git_path_fetch_head(the_repository);
2015-06-18 12:54:02 +02:00
FILE *fp;
struct strbuf sb = STRBUF_INIT;
struct object_id oid;
2015-06-18 12:54:02 +02:00
fp = xfopen(filename, "r");
while (strbuf_getline_lf(&sb, fp) != EOF) {
const char *p;
if (parse_oid_hex(sb.buf, &oid, &p))
continue; /* invalid line: does not start with object ID */
if (starts_with(p, "\tnot-for-merge\t"))
2015-06-18 12:54:02 +02:00
continue; /* ref is not-for-merge */
oid_array_append(merge_heads, &oid);
2015-06-18 12:54:02 +02:00
}
fclose(fp);
strbuf_release(&sb);
}
/**
* Used by die_no_merge_candidates() as a for_each_remote() callback to
* retrieve the name of the remote if the repository only has one remote.
*/
static int get_only_remote(struct remote *remote, void *cb_data)
{
const char **remote_name = cb_data;
if (*remote_name)
return -1;
*remote_name = remote->name;
return 0;
}
/**
* Dies with the appropriate reason for why there are no merge candidates:
*
* 1. We fetched from a specific remote, and a refspec was given, but it ended
* up not fetching anything. This is usually because the user provided a
* wildcard refspec which had no matches on the remote end.
*
* 2. We fetched from a non-default remote, but didn't specify a branch to
* merge. We can't use the configured one because it applies to the default
* remote, thus the user must specify the branches to merge.
*
* 3. We fetched from the branch's or repo's default remote, but:
*
* a. We are not on a branch, so there will never be a configured branch to
* merge with.
*
* b. We are on a branch, but there is no configured branch to merge with.
*
* 4. We fetched from the branch's or repo's default remote, but the configured
* branch to merge didn't get fetched. (Either it doesn't exist, or wasn't
* part of the configured fetch refspec.)
*/
static void NORETURN die_no_merge_candidates(const char *repo, const char **refspecs)
{
struct branch *curr_branch = branch_get("HEAD");
const char *remote = curr_branch ? curr_branch->remote_name : NULL;
if (*refspecs) {
if (opt_rebase)
fprintf_ln(stderr, _("There is no candidate for rebasing against among the refs that you just fetched."));
else
fprintf_ln(stderr, _("There are no candidates for merging among the refs that you just fetched."));
2015-06-18 12:54:02 +02:00
fprintf_ln(stderr, _("Generally this means that you provided a wildcard refspec which had no\n"
"matches on the remote end."));
} else if (repo && curr_branch && (!remote || strcmp(repo, remote))) {
fprintf_ln(stderr, _("You asked to pull from the remote '%s', but did not specify\n"
"a branch. Because this is not the default configured remote\n"
"for your current branch, you must specify a branch on the command line."),
repo);
} else if (!curr_branch) {
fprintf_ln(stderr, _("You are not currently on a branch."));
if (opt_rebase)
fprintf_ln(stderr, _("Please specify which branch you want to rebase against."));
else
fprintf_ln(stderr, _("Please specify which branch you want to merge with."));
2015-06-18 12:54:02 +02:00
fprintf_ln(stderr, _("See git-pull(1) for details."));
fprintf(stderr, "\n");
fprintf_ln(stderr, " git pull %s %s", _("<remote>"), _("<branch>"));
2015-06-18 12:54:02 +02:00
fprintf(stderr, "\n");
} else if (!curr_branch->merge_nr) {
const char *remote_name = NULL;
if (for_each_remote(get_only_remote, &remote_name) || !remote_name)
remote_name = _("<remote>");
2015-06-18 12:54:02 +02:00
fprintf_ln(stderr, _("There is no tracking information for the current branch."));
if (opt_rebase)
fprintf_ln(stderr, _("Please specify which branch you want to rebase against."));
else
fprintf_ln(stderr, _("Please specify which branch you want to merge with."));
2015-06-18 12:54:02 +02:00
fprintf_ln(stderr, _("See git-pull(1) for details."));
fprintf(stderr, "\n");
fprintf_ln(stderr, " git pull %s %s", _("<remote>"), _("<branch>"));
2015-06-18 12:54:02 +02:00
fprintf(stderr, "\n");
fprintf_ln(stderr, _("If you wish to set tracking information for this branch you can do so with:"));
fprintf(stderr, "\n");
fprintf_ln(stderr, " git branch --set-upstream-to=%s/%s %s\n",
remote_name, _("<branch>"), curr_branch->name);
2015-06-18 12:54:02 +02:00
} else
fprintf_ln(stderr, _("Your configuration specifies to merge with the ref '%s'\n"
"from the remote, but no such ref was fetched."),
*curr_branch->merge_name);
exit(1);
}
/**
* Parses argv into [<repo> [<refspecs>...]], returning their values in `repo`
* as a string and `refspecs` as a null-terminated array of strings. If `repo`
* is not provided in argv, it is set to NULL.
*/
static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
const char ***refspecs)
{
if (argc > 0) {
*repo = *argv++;
argc--;
} else
*repo = NULL;
*refspecs = argv;
}
/**
* Runs git-fetch, returning its exit status. `repo` and `refspecs` are the
* repository and refspecs to fetch, or NULL if they are not provided.
*/
static int run_fetch(const char *repo, const char **refspecs)
{
struct argv_array args = ARGV_ARRAY_INIT;
int ret;
argv_array_pushl(&args, "fetch", "--update-head-ok", NULL);
/* Shared options */
argv_push_verbosity(&args);
if (opt_progress)
argv_array_push(&args, opt_progress);
/* Options passed to git-fetch */
if (opt_all)
argv_array_push(&args, opt_all);
if (opt_append)
argv_array_push(&args, opt_append);
if (opt_upload_pack)
argv_array_push(&args, opt_upload_pack);
argv_push_force(&args);
if (opt_tags)
argv_array_push(&args, opt_tags);
if (opt_prune)
argv_array_push(&args, opt_prune);
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
switch (recurse_submodules) {
case RECURSE_SUBMODULES_ON:
argv_array_push(&args, "--recurse-submodules=on");
break;
case RECURSE_SUBMODULES_OFF:
argv_array_push(&args, "--recurse-submodules=no");
break;
case RECURSE_SUBMODULES_ON_DEMAND:
argv_array_push(&args, "--recurse-submodules=on-demand");
break;
default:
BUG("submodule recursion option not understood");
}
if (max_children)
argv_array_push(&args, max_children);
if (opt_dry_run)
argv_array_push(&args, "--dry-run");
if (opt_keep)
argv_array_push(&args, opt_keep);
if (opt_depth)
argv_array_push(&args, opt_depth);
if (opt_unshallow)
argv_array_push(&args, opt_unshallow);
if (opt_update_shallow)
argv_array_push(&args, opt_update_shallow);
if (opt_refmap)
argv_array_push(&args, opt_refmap);
if (opt_ipv4)
argv_array_push(&args, opt_ipv4);
if (opt_ipv6)
argv_array_push(&args, opt_ipv6);
if (repo) {
argv_array_push(&args, repo);
argv_array_pushv(&args, refspecs);
} else if (*refspecs)
BUG("refspecs without repo?");
ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
argv_array_clear(&args);
return ret;
}
/**
* "Pulls into void" by branching off merge_head.
*/
static int pull_into_void(const struct object_id *merge_head,
const struct object_id *curr_head)
{
if (opt_verify_signatures) {
struct commit *commit;
commit = lookup_commit(the_repository, merge_head);
if (!commit)
die(_("unable to access commit %s"),
oid_to_hex(merge_head));
verify_merge_signature(commit, opt_verbosity);
}
/*
* Two-way merge: we treat the index as based on an empty tree,
* and try to fast-forward to HEAD. This ensures we will not lose
* index/worktree changes that the user already made on the unborn
* branch.
*/
if (checkout_fast_forward(the_repository,
the_hash_algo->empty_tree,
merge_head, 0))
return 1;
if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
return 1;
return 0;
}
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
static int rebase_submodules(void)
{
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdin = 1;
argv_array_pushl(&cp.args, "submodule", "update",
"--recursive", "--rebase", NULL);
argv_push_verbosity(&cp.args);
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
return run_command(&cp);
}
static int update_submodules(void)
{
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
cp.no_stdin = 1;
argv_array_pushl(&cp.args, "submodule", "update",
"--recursive", "--checkout", NULL);
argv_push_verbosity(&cp.args);
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
return run_command(&cp);
}
/**
* Runs git-merge, returning its exit status.
*/
static int run_merge(void)
{
int ret;
struct argv_array args = ARGV_ARRAY_INIT;
argv_array_pushl(&args, "merge", NULL);
/* Shared options */
argv_push_verbosity(&args);
if (opt_progress)
argv_array_push(&args, opt_progress);
/* Options passed to git-merge */
if (opt_diffstat)
argv_array_push(&args, opt_diffstat);
if (opt_log)
argv_array_push(&args, opt_log);
if (opt_signoff)
argv_array_push(&args, opt_signoff);
if (opt_squash)
argv_array_push(&args, opt_squash);
if (opt_commit)
argv_array_push(&args, opt_commit);
if (opt_edit)
argv_array_push(&args, opt_edit);
if (cleanup_arg)
argv_array_pushf(&args, "--cleanup=%s", cleanup_arg);
if (opt_ff)
argv_array_push(&args, opt_ff);
if (opt_verify_signatures)
argv_array_push(&args, opt_verify_signatures);
argv_array_pushv(&args, opt_strategies.argv);
argv_array_pushv(&args, opt_strategy_opts.argv);
if (opt_gpg_sign)
argv_array_push(&args, opt_gpg_sign);
if (opt_allow_unrelated_histories > 0)
argv_array_push(&args, "--allow-unrelated-histories");
argv_array_push(&args, "FETCH_HEAD");
ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
argv_array_clear(&args);
return ret;
}
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
/**
* Returns remote's upstream branch for the current branch. If remote is NULL,
* the current branch's configured default remote is used. Returns NULL if
* `remote` does not name a valid remote, HEAD does not point to a branch,
* remote is not the branch's configured remote or the branch does not have any
* configured upstream branch.
*/
static const char *get_upstream_branch(const char *remote)
{
struct remote *rm;
struct branch *curr_branch;
const char *curr_branch_remote;
rm = remote_get(remote);
if (!rm)
return NULL;
curr_branch = branch_get("HEAD");
if (!curr_branch)
return NULL;
curr_branch_remote = remote_for_branch(curr_branch, NULL);
assert(curr_branch_remote);
if (strcmp(curr_branch_remote, rm->name))
return NULL;
return branch_get_upstream(curr_branch, NULL);
}
/**
* Derives the remote-tracking branch from the remote and refspec.
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
*
* FIXME: The current implementation assumes the default mapping of
* refs/heads/<branch_name> to refs/remotes/<remote_name>/<branch_name>.
*/
static const char *get_tracking_branch(const char *remote, const char *refspec)
{
struct refspec_item spec;
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
const char *spec_src;
const char *merge_branch;
refspec_item_init_or_die(&spec, refspec, REFSPEC_FETCH);
spec_src = spec.src;
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (!*spec_src || !strcmp(spec_src, "HEAD"))
spec_src = "HEAD";
else if (skip_prefix(spec_src, "heads/", &spec_src))
;
else if (skip_prefix(spec_src, "refs/heads/", &spec_src))
;
else if (starts_with(spec_src, "refs/") ||
starts_with(spec_src, "tags/") ||
starts_with(spec_src, "remotes/"))
spec_src = "";
if (*spec_src) {
if (!strcmp(remote, "."))
merge_branch = mkpath("refs/heads/%s", spec_src);
else
merge_branch = mkpath("refs/remotes/%s/%s", remote, spec_src);
} else
merge_branch = NULL;
refspec_item_clear(&spec);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
return merge_branch;
}
/**
* Given the repo and refspecs, sets fork_point to the point at which the
* current branch forked from its remote-tracking branch. Returns 0 on success,
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
* -1 on failure.
*/
static int get_rebase_fork_point(struct object_id *fork_point, const char *repo,
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
const char *refspec)
{
int ret;
struct branch *curr_branch;
const char *remote_branch;
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf sb = STRBUF_INIT;
curr_branch = branch_get("HEAD");
if (!curr_branch)
return -1;
if (refspec)
remote_branch = get_tracking_branch(repo, refspec);
else
remote_branch = get_upstream_branch(repo);
if (!remote_branch)
return -1;
argv_array_pushl(&cp.args, "merge-base", "--fork-point",
remote_branch, curr_branch->name, NULL);
cp.no_stdin = 1;
cp.no_stderr = 1;
cp.git_cmd = 1;
ret = capture_command(&cp, &sb, GIT_MAX_HEXSZ);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (ret)
goto cleanup;
ret = get_oid_hex(sb.buf, fork_point);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (ret)
goto cleanup;
cleanup:
strbuf_release(&sb);
return ret ? -1 : 0;
}
/**
* Sets merge_base to the octopus merge base of curr_head, merge_head and
* fork_point. Returns 0 if a merge base is found, 1 otherwise.
*/
static int get_octopus_merge_base(struct object_id *merge_base,
const struct object_id *curr_head,
const struct object_id *merge_head,
const struct object_id *fork_point)
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
{
struct commit_list *revs = NULL, *result;
commit_list_insert(lookup_commit_reference(the_repository, curr_head),
&revs);
commit_list_insert(lookup_commit_reference(the_repository, merge_head),
&revs);
if (!is_null_oid(fork_point))
commit_list_insert(lookup_commit_reference(the_repository, fork_point),
&revs);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
result = get_octopus_merge_bases(revs);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
free_commit_list(revs);
reduce_heads_replace(&result);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (!result)
return 1;
oidcpy(merge_base, &result->item->object.oid);
free_commit_list(result);
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
return 0;
}
/**
* Given the current HEAD oid, the merge head returned from git-fetch and the
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
* fork point calculated by get_rebase_fork_point(), runs git-rebase with the
* appropriate arguments and returns its exit status.
*/
static int run_rebase(const struct object_id *curr_head,
const struct object_id *merge_head,
const struct object_id *fork_point)
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
{
int ret;
struct object_id oct_merge_base;
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
struct argv_array args = ARGV_ARRAY_INIT;
if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point))
if (!is_null_oid(fork_point) && oideq(&oct_merge_base, fork_point))
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
fork_point = NULL;
argv_array_push(&args, "rebase");
/* Shared options */
argv_push_verbosity(&args);
/* Options passed to git-rebase */
if (opt_rebase == REBASE_MERGES)
argv_array_push(&args, "--rebase-merges");
else if (opt_rebase == REBASE_PRESERVE)
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
argv_array_push(&args, "--preserve-merges");
else if (opt_rebase == REBASE_INTERACTIVE)
argv_array_push(&args, "--interactive");
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (opt_diffstat)
argv_array_push(&args, opt_diffstat);
argv_array_pushv(&args, opt_strategies.argv);
argv_array_pushv(&args, opt_strategy_opts.argv);
if (opt_gpg_sign)
argv_array_push(&args, opt_gpg_sign);
if (opt_autostash == 0)
argv_array_push(&args, "--no-autostash");
else if (opt_autostash == 1)
argv_array_push(&args, "--autostash");
if (opt_verify_signatures &&
!strcmp(opt_verify_signatures, "--verify-signatures"))
warning(_("ignoring --verify-signatures for rebase"));
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
argv_array_push(&args, "--onto");
argv_array_push(&args, oid_to_hex(merge_head));
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (fork_point && !is_null_oid(fork_point))
argv_array_push(&args, oid_to_hex(fork_point));
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
else
argv_array_push(&args, oid_to_hex(merge_head));
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
argv_array_clear(&args);
return ret;
}
int cmd_pull(int argc, const char **argv, const char *prefix)
{
const char *repo, **refspecs;
struct oid_array merge_heads = OID_ARRAY_INIT;
struct object_id orig_head, curr_head;
struct object_id rebase_fork_point;
int autostash;
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
git_config(git_pull_config, NULL);
argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
if (cleanup_arg)
/*
* this only checks the validity of cleanup_arg; we don't need
* a valid value for use_editor
*/
get_cleanup_mode(cleanup_arg, 0);
parse_repo_refspecs(argc, argv, &repo, &refspecs);
if (!opt_ff)
opt_ff = xstrdup_or_null(config_get_ff());
if (opt_rebase < 0)
opt_rebase = config_get_rebase();
if (read_cache_unmerged())
die_resolve_conflict("pull");
if (file_exists(git_path_merge_head(the_repository)))
die_conclude_merge();
if (get_oid("HEAD", &orig_head))
oidclr(&orig_head);
if (!opt_rebase && opt_autostash != -1)
die(_("--[no-]autostash option is only valid with --rebase."));
autostash = config_autostash;
if (opt_rebase) {
if (opt_autostash != -1)
autostash = opt_autostash;
if (is_null_oid(&orig_head) && !is_cache_unborn())
die(_("Updating an unborn branch with changes added to the index."));
if (!autostash)
require_clean_work_tree(the_repository,
N_("pull with rebase"),
_("please commit or stash them."), 1, 0);
if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs))
oidclr(&rebase_fork_point);
}
pull: teach git pull about --rebase Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the --rebase option is set, git-rebase is run instead of git-merge. Re-implement this by introducing run_rebase(), which is called instead of run_merge() if opt_rebase is a true value. Since c85c792 (pull --rebase: be cleverer with rebased upstream branches, 2008-01-26), git-pull handles the case where the upstream branch was rebased since it was last fetched. The fork point (old remote ref) of the branch from the upstream branch is calculated before fetch, and then rebased from onto the new remote head (merge_head) after fetch. Re-implement this by introducing get_merge_branch_2() and get_merge_branch_1() to find the upstream branch for the specified/current branch, and get_rebase_fork_point() which will find the fork point between the upstream branch and current branch. However, the above change created a problem where git-rebase cannot detect commits that are already upstream, and thus may result in unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring the above old remote ref if it is contained within the merge base of the merge head and the current branch. This is re-implemented in run_rebase() where fork_point is not used if it is the merge base returned by get_octopus_merge_base(). Helped-by: Stefan Beller <sbeller@google.com> Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Paul Tan <pyokagan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-18 12:54:08 +02:00
if (run_fetch(repo, refspecs))
return 1;
if (opt_dry_run)
return 0;
if (get_oid("HEAD", &curr_head))
oidclr(&curr_head);
if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) &&
!oideq(&orig_head, &curr_head)) {
/*
* The fetch involved updating the current branch.
*
* The working tree and the index file are still based on
* orig_head commit, but we are merging into curr_head.
* Update the working tree to match curr_head.
*/
warning(_("fetch updated the current branch head.\n"
"fast-forwarding your working tree from\n"
"commit %s."), oid_to_hex(&orig_head));
if (checkout_fast_forward(the_repository, &orig_head,
&curr_head, 0))
die(_("Cannot fast-forward your working tree.\n"
"After making sure that you saved anything precious from\n"
"$ git diff %s\n"
"output, run\n"
"$ git reset --hard\n"
"to recover."), oid_to_hex(&orig_head));
}
2015-06-18 12:54:02 +02:00
get_merge_heads(&merge_heads);
if (!merge_heads.nr)
die_no_merge_candidates(repo, refspecs);
if (is_null_oid(&orig_head)) {
if (merge_heads.nr > 1)
die(_("Cannot merge multiple branches into empty head."));
return pull_into_void(merge_heads.oid, &curr_head);
}
if (opt_rebase && merge_heads.nr > 1)
die(_("Cannot rebase onto multiple branches."));
if (opt_rebase) {
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
int ret = 0;
if ((recurse_submodules == RECURSE_SUBMODULES_ON ||
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) &&
submodule_touches_in_range(the_repository, &rebase_fork_point, &curr_head))
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
die(_("cannot rebase with locally recorded submodule modifications"));
if (!autostash) {
struct commit_list *list = NULL;
struct commit *merge_head, *head;
head = lookup_commit_reference(the_repository,
&orig_head);
commit_list_insert(head, &list);
merge_head = lookup_commit_reference(the_repository,
&merge_heads.oid[0]);
if (is_descendant_of(merge_head, list)) {
/* we can fast-forward this without invoking rebase */
opt_ff = "--ff-only";
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
ret = run_merge();
}
}
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
ret = rebase_submodules();
return ret;
} else {
pull: optionally rebase submodules (remote submodule changes only) Teach pull to optionally update submodules when '--recurse-submodules' is provided. This will teach pull to run 'submodule update --rebase' when the '--recurse-submodules' and '--rebase' flags are given under specific circumstances. On a rebase workflow: ===================== 1. Both sides change the submodule ------------------------------ Let's assume the following history in a submodule: H---I---J---K---L local branch \ M---N---O---P remote branch and the following in the superproject (recorded submodule in parens): A(H)---B(I)---F(K)---G(L) local branch \ C(N)---D(N)---E(P) remote branch In an ideal world this would rebase the submodule and rewrite the submodule pointers that the superproject points at such that the superproject looks like A(H)---B(I) F(K')---G(L') rebased branch \ / C(N)---D(N)---E(P) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch And if a conflict arises in the submodule the superproject rebase would stop at that commit at which the submodule conflict occurs. Currently a "pull --rebase" in the superproject produces a merge conflict as the submodule pointer changes are conflicting and cannot be resolved. 2. Local submodule changes only ----------------------- Assuming histories as above, except that the remote branch would not contain submodule changes, then a result as A(H)---B(I) F(K)---G(L) rebased branch \ / C(I)---D(I)---E(I) remote branch is desire-able. This is what currently happens in rebase. If the recursive flag is given, the ideal git would produce a superproject as: A(H)---B(I) F(K')---G(L') rebased branch (incl. sub rebase!) \ / C(I)---D(I)---E(I) remote branch and the submodule as: J---K---L (old dangeling tip) / H---I J'---K'---L' locally rebased branch \ / M---N---O---P advanced branch This patch doesn't address this issue, however a test is added that this fails up front. 3. Remote submodule changes only ---------------------- Assuming histories as in (1) except that the local superproject branch would not have touched the submodule the rebase already works out in the superproject with no conflicts: A(H)---B(I) F(P)---G(P) rebased branch (no sub changes) \ / C(N)---D(N)---E(P) remote branch The recurse flag as presented in this patch would additionally update the submodule as: H---I J'---K'---L' rebased branch \ / M---N---O---P remote branch As neither J, K, L nor J', K', L' are referred to from the superproject, no rewriting of the superproject commits is required. Conclusion for 'pull --rebase --recursive' ----------------------------------------- If there are no local superproject changes it is sufficient to call "submodule update --rebase" as this produces the desired results. In case of conflicts, the behavior is the same as in 'submodule update --recursive' which is assumed to be sane. This patch implements (3) only. On a merge workflow: ==================== We'll start off with the same underlying DAG as in (1) in the rebase workflow. So in an ideal world a 'pull --merge --recursive' would produce this: H---I---J---K---L----X \ / M---N---O---P with X as the new merge-commit in the submodule and the superproject as: A(H)---B(I)---F(K)---G(L)---Y(X) \ / C(N)---D(N)---E(P) However modifying the submodules on the fly is not supported in git-merge such that Y(X) is not easy to produce in a single patch. In fact git-merge doesn't know about submodules at all. However when at least one side does not contain commits touching the submodule at all, then we do not need to perform the merge for the submodule but a fast-forward can be done via checking out either L or P in the submodule. This strategy is implemented in 68d03e4a6e (Implement automatic fast-forward merge for submodules, 2010-07-07) already, so to align with the rebase behavior we need to also update the worktree of the submodule. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-23 21:13:02 +02:00
int ret = run_merge();
if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
ret = update_submodules();
return ret;
}
}