зеркало из https://github.com/microsoft/git.git
Merge branch 'jt/rebase-allow-duplicate'
Allow "git rebase" to reapply all local commits, even if the may be already in the upstream, without checking first. * jt/rebase-allow-duplicate: rebase --merge: optionally skip upstreamed commits
This commit is contained in:
Коммит
d6d561db1c
|
@ -279,7 +279,8 @@ See also INCOMPATIBLE OPTIONS below.
|
|||
+
|
||||
Note that commits which start empty are kept (unless --no-keep-empty
|
||||
is specified), and commits which are clean cherry-picks (as determined
|
||||
by `git log --cherry-mark ...`) are always dropped.
|
||||
by `git log --cherry-mark ...`) are detected and dropped as a
|
||||
preliminary step (unless --reapply-cherry-picks is passed).
|
||||
+
|
||||
See also INCOMPATIBLE OPTIONS below.
|
||||
|
||||
|
@ -304,6 +305,24 @@ see the --empty flag.
|
|||
+
|
||||
See also INCOMPATIBLE OPTIONS below.
|
||||
|
||||
--reapply-cherry-picks::
|
||||
--no-reapply-cherry-picks::
|
||||
Reapply all clean cherry-picks of any upstream commit instead
|
||||
of preemptively dropping them. (If these commits then become
|
||||
empty after rebasing, because they contain a subset of already
|
||||
upstream changes, the behavior towards them is controlled by
|
||||
the `--empty` flag.)
|
||||
+
|
||||
By default (or if `--no-reapply-cherry-picks` is given), these commits
|
||||
will be automatically dropped. Because this necessitates reading all
|
||||
upstream commits, this can be expensive in repos with a large number
|
||||
of upstream commits that need to be read.
|
||||
+
|
||||
`--reapply-cherry-picks` allows rebase to forgo reading all upstream
|
||||
commits, potentially improving performance.
|
||||
+
|
||||
See also INCOMPATIBLE OPTIONS below.
|
||||
|
||||
--allow-empty-message::
|
||||
No-op. Rebasing commits with an empty message used to fail
|
||||
and this option would override that behavior, allowing commits
|
||||
|
@ -604,6 +623,7 @@ are incompatible with the following options:
|
|||
* --exec
|
||||
* --no-keep-empty
|
||||
* --empty=
|
||||
* --reapply-cherry-picks
|
||||
* --edit-todo
|
||||
* --root when used in combination with --onto
|
||||
|
||||
|
@ -1020,7 +1040,8 @@ Only works if the changes (patch IDs based on the diff contents) on
|
|||
'subsystem' did.
|
||||
|
||||
In that case, the fix is easy because 'git rebase' knows to skip
|
||||
changes that are already present in the new upstream. So if you say
|
||||
changes that are already present in the new upstream (unless
|
||||
`--reapply-cherry-picks` is given). So if you say
|
||||
(assuming you're on 'topic')
|
||||
------------
|
||||
$ git rebase subsystem
|
||||
|
|
|
@ -96,6 +96,7 @@ struct rebase_options {
|
|||
struct strbuf git_format_patch_opt;
|
||||
int reschedule_failed_exec;
|
||||
int use_legacy_rebase;
|
||||
int reapply_cherry_picks;
|
||||
};
|
||||
|
||||
#define REBASE_OPTIONS_INIT { \
|
||||
|
@ -387,6 +388,7 @@ static int run_sequencer_rebase(struct rebase_options *opts,
|
|||
flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
|
||||
flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
|
||||
flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
|
||||
flags |= opts->reapply_cherry_picks ? TODO_LIST_REAPPLY_CHERRY_PICKS : 0;
|
||||
|
||||
switch (command) {
|
||||
case ACTION_NONE: {
|
||||
|
@ -1586,6 +1588,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
OPT_BOOL(0, "reschedule-failed-exec",
|
||||
&reschedule_failed_exec,
|
||||
N_("automatically re-schedule any `exec` that fails")),
|
||||
OPT_BOOL(0, "reapply-cherry-picks", &options.reapply_cherry_picks,
|
||||
N_("apply all changes, even those already present upstream")),
|
||||
OPT_END(),
|
||||
};
|
||||
int i;
|
||||
|
@ -1829,6 +1833,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||
if (options.empty != EMPTY_UNSPECIFIED)
|
||||
imply_merge(&options, "--empty");
|
||||
|
||||
if (options.reapply_cherry_picks)
|
||||
imply_merge(&options, "--reapply-cherry-picks");
|
||||
|
||||
if (gpg_sign)
|
||||
options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
|
||||
|
||||
|
|
|
@ -4852,12 +4852,13 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
|||
int keep_empty = flags & TODO_LIST_KEEP_EMPTY;
|
||||
const char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? "p" : "pick";
|
||||
int rebase_merges = flags & TODO_LIST_REBASE_MERGES;
|
||||
int reapply_cherry_picks = flags & TODO_LIST_REAPPLY_CHERRY_PICKS;
|
||||
|
||||
repo_init_revisions(r, &revs, NULL);
|
||||
revs.verbose_header = 1;
|
||||
if (!rebase_merges)
|
||||
revs.max_parents = 1;
|
||||
revs.cherry_mark = 1;
|
||||
revs.cherry_mark = !reapply_cherry_picks;
|
||||
revs.limited = 1;
|
||||
revs.reverse = 1;
|
||||
revs.right_only = 1;
|
||||
|
|
|
@ -150,7 +150,7 @@ int sequencer_remove_state(struct replay_opts *opts);
|
|||
* `--onto`, we do not want to re-generate the root commits.
|
||||
*/
|
||||
#define TODO_LIST_ROOT_WITH_ONTO (1U << 6)
|
||||
|
||||
#define TODO_LIST_REAPPLY_CHERRY_PICKS (1U << 7)
|
||||
|
||||
int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
||||
const char **argv, unsigned flags);
|
||||
|
|
|
@ -162,4 +162,81 @@ test_expect_success 'rebase --skip works with two conflicts in a row' '
|
|||
git rebase --skip
|
||||
'
|
||||
|
||||
test_expect_success '--reapply-cherry-picks' '
|
||||
git init repo &&
|
||||
|
||||
# O(1-10) -- O(1-11) -- O(0-10) master
|
||||
# \
|
||||
# -- O(1-11) -- O(1-12) otherbranch
|
||||
|
||||
printf "Line %d\n" $(test_seq 1 10) >repo/file.txt &&
|
||||
git -C repo add file.txt &&
|
||||
git -C repo commit -m "base commit" &&
|
||||
|
||||
printf "Line %d\n" $(test_seq 1 11) >repo/file.txt &&
|
||||
git -C repo commit -a -m "add 11" &&
|
||||
|
||||
printf "Line %d\n" $(test_seq 0 10) >repo/file.txt &&
|
||||
git -C repo commit -a -m "add 0 delete 11" &&
|
||||
|
||||
git -C repo checkout -b otherbranch HEAD^^ &&
|
||||
printf "Line %d\n" $(test_seq 1 11) >repo/file.txt &&
|
||||
git -C repo commit -a -m "add 11 in another branch" &&
|
||||
|
||||
printf "Line %d\n" $(test_seq 1 12) >repo/file.txt &&
|
||||
git -C repo commit -a -m "add 12 in another branch" &&
|
||||
|
||||
# Regular rebase fails, because the 1-11 commit is deduplicated
|
||||
test_must_fail git -C repo rebase --merge master 2> err &&
|
||||
test_i18ngrep "error: could not apply.*add 12 in another branch" err &&
|
||||
git -C repo rebase --abort &&
|
||||
|
||||
# With --reapply-cherry-picks, it works
|
||||
git -C repo rebase --merge --reapply-cherry-picks master
|
||||
'
|
||||
|
||||
test_expect_success '--reapply-cherry-picks refrains from reading unneeded blobs' '
|
||||
git init server &&
|
||||
|
||||
# O(1-10) -- O(1-11) -- O(1-12) master
|
||||
# \
|
||||
# -- O(0-10) otherbranch
|
||||
|
||||
printf "Line %d\n" $(test_seq 1 10) >server/file.txt &&
|
||||
git -C server add file.txt &&
|
||||
git -C server commit -m "merge base" &&
|
||||
|
||||
printf "Line %d\n" $(test_seq 1 11) >server/file.txt &&
|
||||
git -C server commit -a -m "add 11" &&
|
||||
|
||||
printf "Line %d\n" $(test_seq 1 12) >server/file.txt &&
|
||||
git -C server commit -a -m "add 12" &&
|
||||
|
||||
git -C server checkout -b otherbranch HEAD^^ &&
|
||||
printf "Line %d\n" $(test_seq 0 10) >server/file.txt &&
|
||||
git -C server commit -a -m "add 0" &&
|
||||
|
||||
test_config -C server uploadpack.allowfilter 1 &&
|
||||
test_config -C server uploadpack.allowanysha1inwant 1 &&
|
||||
|
||||
git clone --filter=blob:none "file://$(pwd)/server" client &&
|
||||
git -C client checkout origin/master &&
|
||||
git -C client checkout origin/otherbranch &&
|
||||
|
||||
# Sanity check to ensure that the blobs from the merge base and "add
|
||||
# 11" are missing
|
||||
git -C client rev-list --objects --all --missing=print >missing_list &&
|
||||
MERGE_BASE_BLOB=$(git -C server rev-parse master^^:file.txt) &&
|
||||
ADD_11_BLOB=$(git -C server rev-parse master^:file.txt) &&
|
||||
grep "[?]$MERGE_BASE_BLOB" missing_list &&
|
||||
grep "[?]$ADD_11_BLOB" missing_list &&
|
||||
|
||||
git -C client rebase --merge --reapply-cherry-picks origin/master &&
|
||||
|
||||
# The blob from the merge base had to be fetched, but not "add 11"
|
||||
git -C client rev-list --objects --all --missing=print >missing_list &&
|
||||
! grep "[?]$MERGE_BASE_BLOB" missing_list &&
|
||||
grep "[?]$ADD_11_BLOB" missing_list
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче