2011-08-04 10:39:11 +00:00
|
|
|
#ifndef SEQUENCER_H
|
|
|
|
#define SEQUENCER_H
|
|
|
|
|
2018-08-15 17:54:05 +00:00
|
|
|
#include "strbuf.h"
|
2023-04-10 09:08:28 +00:00
|
|
|
#include "strvec.h"
|
2019-12-06 16:06:11 +00:00
|
|
|
#include "wt-status.h"
|
2018-08-15 17:54:05 +00:00
|
|
|
|
|
|
|
struct commit;
|
2023-02-24 00:09:22 +00:00
|
|
|
struct index_state;
|
2018-11-10 05:48:56 +00:00
|
|
|
struct repository;
|
2018-08-15 17:54:05 +00:00
|
|
|
|
2018-01-24 12:34:22 +00:00
|
|
|
const char *git_path_commit_editmsg(void);
|
2018-08-10 16:51:28 +00:00
|
|
|
const char *rebase_path_todo(void);
|
2019-03-05 19:18:03 +00:00
|
|
|
const char *rebase_path_todo_backup(void);
|
rebase-interactive: warn if commit is dropped with `rebase --edit-todo'
When set to "warn" or "error", `rebase.missingCommitsCheck' would make
`rebase -i' warn if the user removed commits from the todo list to
prevent mistakes. Unfortunately, `rebase --edit-todo' and `rebase
--continue' don't take it into account.
This adds the ability for `rebase --edit-todo' and `rebase --continue'
to check if commits were dropped by the user. As both edit_todo_list()
and complete_action() parse the todo list and check for dropped commits,
the code doing so in the latter is removed to reduce duplication.
`edit_todo_list_advice' is removed from sequencer.c as it is no longer
used there.
This changes when a backup of the todo list is made. Until now, it was
saved only once, before the initial edit. Now, it is also made if the
original todo list has no errors or no dropped commits. Thus, the
backup should be error-free. Without this, sequencer_continue()
(`rebase --continue') could only compare the current todo list against
the original, unedited list. Before this change, this file was only
used by edit_todo_list() and `rebase -p' to create the backup before
the initial edit, and check_todo_list_from_file(), only used by
`rebase -p' to check for dropped commits after its own initial edit.
If the edited list has an error, a file, `dropped', is created to
report the issue. Otherwise, it is deleted. Usually, the edited list
is compared against the list before editing, but if this file exists,
it will be compared to the backup. Also, if the file exists,
sequencer_continue() checks the list for dropped commits. If the
check was performed every time, it would fail when resuming a rebase
after resolving a conflict, as the backup will contain commits that
were picked, but they will not be in the new list. It's safe to
ignore this check if `dropped' does not exist, because that means that
no errors were found at the last edition, so any missing commits here
have already been picked.
Five tests are added to t3404. The tests for
`rebase.missingCommitsCheck = warn' and `rebase.missingCommitsCheck =
error' have a similar structure. First, we start a rebase with an
incorrect command on the first line. Then, we edit the todo list,
removing the first and the last lines. This demonstrates that
`--edit-todo' notices dropped commits, but not when the command is
incorrect. Then, we restore the original todo list, and edit it to
remove the last line. This demonstrates that if we add a commit after
the initial edit, then remove it, `--edit-todo' will notice that it
has been dropped. Then, the actual rebase takes place. In the third
test, it is also checked that `--continue' will refuse to resume the
rebase if commits were dropped. The fourth test checks that no errors
are raised when resuming a rebase after resolving a conflict, the fifth
checks that no errors are raised when editing the todo list after
pausing the rebase.
Signed-off-by: Alban Gruin <alban.gruin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-01-28 21:12:46 +00:00
|
|
|
const char *rebase_path_dropped(void);
|
2011-08-04 10:39:11 +00:00
|
|
|
|
2013-02-12 10:17:35 +00:00
|
|
|
#define APPEND_SIGNOFF_DEDUP (1u << 0)
|
|
|
|
|
2012-01-11 18:15:57 +00:00
|
|
|
enum replay_action {
|
|
|
|
REPLAY_REVERT,
|
2017-01-02 15:26:28 +00:00
|
|
|
REPLAY_PICK,
|
|
|
|
REPLAY_INTERACTIVE_REBASE
|
2012-01-11 18:15:57 +00:00
|
|
|
};
|
|
|
|
|
2017-12-13 11:46:21 +00:00
|
|
|
enum commit_msg_cleanup_mode {
|
|
|
|
COMMIT_MSG_CLEANUP_SPACE,
|
|
|
|
COMMIT_MSG_CLEANUP_NONE,
|
|
|
|
COMMIT_MSG_CLEANUP_SCISSORS,
|
|
|
|
COMMIT_MSG_CLEANUP_ALL
|
|
|
|
};
|
|
|
|
|
2012-01-11 18:15:57 +00:00
|
|
|
struct replay_opts {
|
|
|
|
enum replay_action action;
|
|
|
|
|
sequencer: fix edit handling for cherry-pick and revert messages
save_opts() should save any non-default values. It was intended to do
this, but since most options in struct replay_opts default to 0, it only
saved non-zero values. Unfortunately, this does not always work for
options.edit. Roughly speaking, options.edit had a default value of 0
for cherry-pick but a default value of 1 for revert. Make save_opts()
record a value whenever it differs from the default.
options.edit was also overly simplistic; we had more than two cases.
The behavior that previously existed was as follows:
Non-conflict commits Right after Conflict
revert Edit iff isatty(0) Edit (ignore isatty(0))
cherry-pick No edit See above
Specify --edit Edit (ignore isatty(0)) See above
Specify --no-edit (*) See above
(*) Before stopping for conflicts, No edit is the behavior. After
stopping for conflicts, the --no-edit flag is not saved so see
the first two rows.
However, the expected behavior is:
Non-conflict commits Right after Conflict
revert Edit iff isatty(0) Edit iff isatty(0)
cherry-pick No edit Edit iff isatty(0)
Specify --edit Edit (ignore isatty(0)) Edit (ignore isatty(0))
Specify --no-edit No edit No edit
In order to get the expected behavior, we need to change options.edit
to a tri-state: unspecified, false, or true. When specified, we follow
what it says. When unspecified, we need to check whether the current
commit being created is resolving a conflict as well as consulting
options.action and isatty(0). While at it, add a should_edit() utility
function that compresses options.edit down to a boolean based on the
additional information for the non-conflict case.
continue_single_pick() is the function responsible for resuming after
conflict cases, regardless of whether there is one commit being picked
or many. Make this function stop assuming edit behavior in all cases,
so that it can correctly handle !isatty(0) and specific requests to not
edit the commit message.
Reported-by: Renato Botelho <garga@freebsd.org>
Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-03-31 06:52:20 +00:00
|
|
|
/* Tri-state options: unspecified, false, or true */
|
2012-01-11 18:15:57 +00:00
|
|
|
int edit;
|
sequencer: fix edit handling for cherry-pick and revert messages
save_opts() should save any non-default values. It was intended to do
this, but since most options in struct replay_opts default to 0, it only
saved non-zero values. Unfortunately, this does not always work for
options.edit. Roughly speaking, options.edit had a default value of 0
for cherry-pick but a default value of 1 for revert. Make save_opts()
record a value whenever it differs from the default.
options.edit was also overly simplistic; we had more than two cases.
The behavior that previously existed was as follows:
Non-conflict commits Right after Conflict
revert Edit iff isatty(0) Edit (ignore isatty(0))
cherry-pick No edit See above
Specify --edit Edit (ignore isatty(0)) See above
Specify --no-edit (*) See above
(*) Before stopping for conflicts, No edit is the behavior. After
stopping for conflicts, the --no-edit flag is not saved so see
the first two rows.
However, the expected behavior is:
Non-conflict commits Right after Conflict
revert Edit iff isatty(0) Edit iff isatty(0)
cherry-pick No edit Edit iff isatty(0)
Specify --edit Edit (ignore isatty(0)) Edit (ignore isatty(0))
Specify --no-edit No edit No edit
In order to get the expected behavior, we need to change options.edit
to a tri-state: unspecified, false, or true. When specified, we follow
what it says. When unspecified, we need to check whether the current
commit being created is resolving a conflict as well as consulting
options.action and isatty(0). While at it, add a should_edit() utility
function that compresses options.edit down to a boolean based on the
additional information for the non-conflict case.
continue_single_pick() is the function responsible for resuming after
conflict cases, regardless of whether there is one commit being picked
or many. Make this function stop assuming edit behavior in all cases,
so that it can correctly handle !isatty(0) and specific requests to not
edit the commit message.
Reported-by: Renato Botelho <garga@freebsd.org>
Signed-off-by: Elijah Newren <newren@gmail.com>
Reviewed-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2021-03-31 06:52:20 +00:00
|
|
|
|
|
|
|
/* Boolean options */
|
2012-01-11 18:15:57 +00:00
|
|
|
int record_origin;
|
|
|
|
int no_commit;
|
|
|
|
int signoff;
|
|
|
|
int allow_ff;
|
|
|
|
int allow_rerere_auto;
|
2012-04-11 20:21:53 +00:00
|
|
|
int allow_empty;
|
2012-08-02 10:38:51 +00:00
|
|
|
int allow_empty_message;
|
rebase (interactive-backend): fix handling of commits that become empty
As established in the previous commit and commit b00bf1c9a8dd
(git-rebase: make --allow-empty-message the default, 2018-06-27), the
behavior for rebase with different backends in various edge or corner
cases is often more happenstance than design. This commit addresses
another such corner case: commits which "become empty".
A careful reader may note that there are two types of commits which would
become empty due to a rebase:
* [clean cherry-pick] Commits which are clean cherry-picks of upstream
commits, as determined by `git log --cherry-mark ...`. Re-applying
these commits would result in an empty set of changes and a
duplicative commit message; i.e. these are commits that have
"already been applied" upstream.
* [become empty] Commits which are not empty to start, are not clean
cherry-picks of upstream commits, but which still become empty after
being rebased. This happens e.g. when a commit has changes which
are a strict subset of the changes in an upstream commit, or when
the changes of a commit can be found spread across or among several
upstream commits.
Clearly, in both cases the changes in the commit in question are found
upstream already, but the commit message may not be in the latter case.
When cherry-mark can determine a commit is already upstream, then
because of how cherry-mark works this means the upstream commit message
was about the *exact* same set of changes. Thus, the commit messages
can be assumed to be fully interchangeable (and are in fact likely to be
completely identical). As such, the clean cherry-pick case represents a
case when there is no information to be gained by keeping the extra
commit around. All rebase types have always dropped these commits, and
no one to my knowledge has ever requested that we do otherwise.
For many of the become empty cases (and likely even most), we will also
be able to drop the commit without loss of information -- but this isn't
quite always the case. Since these commits represent cases that were
not clean cherry-picks, there is no upstream commit message explaining
the same set of changes. Projects with good commit message hygiene will
likely have the explanation from our commit message contained within or
spread among the relevant upstream commits, but not all projects run
that way. As such, the commit message of the commit being rebased may
have reasoning that suggests additional changes that should be made to
adapt to the new base, or it may have information that someone wants to
add as a note to another commit, or perhaps someone even wants to create
an empty commit with the commit message as-is.
Junio commented on the "become-empty" types of commits as follows[1]:
WRT a change that ends up being empty (as opposed to a change that
is empty from the beginning), I'd think that the current behaviour
is desireable one. "am" based rebase is solely to transplant an
existing history and want to stop much less than "interactive" one
whose purpose is to polish a series before making it publishable,
and asking for confirmation ("this has become empty--do you want to
drop it?") is more appropriate from the workflow point of view.
[1] https://lore.kernel.org/git/xmqqfu1fswdh.fsf@gitster-ct.c.googlers.com/
I would simply add that his arguments for "am"-based rebases actually
apply to all non-explicitly-interactive rebases. Also, since we are
stating that different cases should have different defaults, it may be
worth providing a flag to allow users to select which behavior they want
for these commits.
Introduce a new command line flag for selecting the desired behavior:
--empty={drop,keep,ask}
with the definitions:
drop: drop commits which become empty
keep: keep commits which become empty
ask: provide the user a chance to interact and pick what to do with
commits which become empty on a case-by-case basis
In line with Junio's suggestion, if the --empty flag is not specified,
pick defaults as follows:
explicitly interactive: ask
otherwise: drop
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-15 21:36:25 +00:00
|
|
|
int drop_redundant_commits;
|
git-cherry-pick: Add keep-redundant-commits option
The git-cherry-pick --allow-empty command by default only preserves empty
commits that were originally empty, i.e only those commits for which
<commit>^{tree} and <commit>^^{tree} are equal. By default commits which are
non-empty, but were made empty by the inclusion of a prior commit on the current
history are filtered out. This option allows us to override that behavior and
include redundant commits as empty commits in the change history.
Note that this patch changes the default behavior of git cherry-pick slightly.
Prior to this patch all commits in a cherry-pick sequence were applied and git
commit was run. The implication here was that, if a commit was redundant, and
the commit did not trigger the fast forward logic, the git commit operation, and
therefore the git cherry-pick operation would fail, displaying the cherry pick
advice (i.e. run git commit --allow-empty). With this patch however, such
redundant commits are automatically skipped without stopping, unless
--keep-redundant-commits is specified, in which case, they are automatically
applied as empty commits.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-20 14:36:15 +00:00
|
|
|
int keep_redundant_commits;
|
2017-01-02 15:26:53 +00:00
|
|
|
int verbose;
|
git-rebase, sequencer: extend --quiet option for the interactive machinery
While 'quiet' and 'interactive' may sound like antonyms, the interactive
machinery actually has logic that implements several
interactive_rebase=implied cases (--exec, --keep-empty, --rebase-merges)
which won't pop up an editor. The rewrite of interactive rebase in C
added a quiet option, though it only turns stats off. Since we want to
make the interactive machinery also take over for git-rebase--merge, it
should fully implement the --quiet option.
git-rebase--interactive was already somewhat quieter than
git-rebase--merge and git-rebase--am, possibly because cherry-pick has
just traditionally been quieter. As such, we only drop a few
informational messages -- "Rebasing (n/m)" and "Successfully rebased..."
Also, for simplicity, remove the differences in how quiet and verbose
options were recorded. Having one be signalled by the presence of a
"verbose" file in the state_dir, while the other was signalled by the
contents of a "quiet" file was just weirdly inconsistent. (This
inconsistency pre-dated the rewrite into C.) Make them consistent by
having them both key off the presence of the file.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-12-11 16:11:36 +00:00
|
|
|
int quiet;
|
2018-12-10 19:04:58 +00:00
|
|
|
int reschedule_failed_exec;
|
2020-08-17 17:40:02 +00:00
|
|
|
int committer_date_is_author_date;
|
2020-08-17 17:40:03 +00:00
|
|
|
int ignore_date;
|
revert: optionally refer to commit in the "reference" format
A typical "git revert" commit uses the full title of the original
commit in its title, and starts its body of the message with:
This reverts commit 8fa7f667cf61386257c00d6e954855cc3215ae91.
This does not encourage the best practice of describing not just
"what" (i.e. "Revert X" on the title says what we did) but "why"
(i.e. and it does not say why X was undesirable).
We can instead phrase this first line of the body to be more like
This reverts commit 8fa7f667 (do this and that, 2022-04-25)
so that the title does not have to be
Revert "do this and that"
We can instead use the title to describe "why" we are reverting the
original commit.
Introduce the "--reference" option to "git revert", and also the
revert.reference configuration variable, which defaults to false, to
tweak the title and the first line of the draft commit message for
when creating a "revert" commit.
When this option is in use, the first line of the pre-filled editor
buffer becomes a comment line that tells the user to say _why_. If
the user exits the editor without touching this line by mistake,
what we prepare to become the first line of the body, i.e. "This
reverts commit 8fa7f667 (do this and that, 2022-04-25)", ends up to
be the title of the resulting commit. This behaviour is designed to
help such a user to identify such a revert in "git log --oneline"
easily so that it can be further reworded with "git rebase -i" later.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-05-27 06:01:39 +00:00
|
|
|
int commit_use_reference;
|
2012-01-11 18:15:57 +00:00
|
|
|
|
|
|
|
int mainline;
|
|
|
|
|
2016-10-21 12:24:13 +00:00
|
|
|
char *gpg_sign;
|
2017-12-13 11:46:21 +00:00
|
|
|
enum commit_msg_cleanup_mode default_msg_cleanup;
|
2019-03-29 11:08:42 +00:00
|
|
|
int explicit_cleanup;
|
2014-01-24 00:50:58 +00:00
|
|
|
|
2012-01-11 18:15:57 +00:00
|
|
|
/* Merge strategy */
|
2020-11-02 23:45:34 +00:00
|
|
|
char *default_strategy; /* from config options */
|
2016-10-21 12:24:13 +00:00
|
|
|
char *strategy;
|
2023-04-10 09:08:28 +00:00
|
|
|
struct strvec xopts;
|
2012-01-11 18:15:57 +00:00
|
|
|
|
2022-11-09 14:21:57 +00:00
|
|
|
/* Reflog */
|
|
|
|
char *reflog_action;
|
|
|
|
|
2018-04-27 20:48:21 +00:00
|
|
|
/* Used by fixup/squash */
|
|
|
|
struct strbuf current_fixups;
|
|
|
|
int current_fixup_count;
|
|
|
|
|
sequencer: learn about the special "fake root commit" handling
When an interactive rebase wants to recreate a root commit, it
- first creates a new, empty root commit,
- checks it out,
- converts the next `pick` command so that it amends the empty root
commit
Introduce support in the sequencer to handle such an empty root commit,
by looking for the file <GIT_DIR>/rebase-merge/squash-onto; if it exists
and contains a commit name, the sequencer will compare the HEAD to said
root commit, and if identical, a new root commit will be created.
While converting scripted code into proper, portable C, we also do away
with the old "amend with an empty commit message, then cherry-pick
without committing, then amend again" dance and replace it with code
that uses the internal API properly to do exactly what we want: create a
new root commit.
To keep the implementation simple, we always spawn `git commit` to create
new root commits.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-03 23:01:17 +00:00
|
|
|
/* placeholder commit for -i --root */
|
|
|
|
struct object_id squash_onto;
|
|
|
|
int have_squash_onto;
|
|
|
|
|
2012-01-11 18:15:57 +00:00
|
|
|
/* Only used by REPLAY_NONE */
|
|
|
|
struct rev_info *revs;
|
2022-11-09 14:21:57 +00:00
|
|
|
|
|
|
|
/* Private use */
|
|
|
|
const char *reflog_message;
|
2012-01-11 18:15:57 +00:00
|
|
|
};
|
2023-04-10 09:08:28 +00:00
|
|
|
#define REPLAY_OPTS_INIT { \
|
|
|
|
.edit = -1, \
|
|
|
|
.action = -1, \
|
|
|
|
.current_fixups = STRBUF_INIT, \
|
|
|
|
.xopts = STRVEC_INIT, \
|
|
|
|
}
|
2012-01-11 18:15:57 +00:00
|
|
|
|
2018-12-29 16:03:59 +00:00
|
|
|
/*
|
|
|
|
* Note that ordering matters in this enum. Not only must it match the mapping
|
|
|
|
* of todo_command_info (in sequencer.c), it is also divided into several
|
|
|
|
* sections that matter. When adding new commands, make sure you add it in the
|
|
|
|
* right section.
|
|
|
|
*/
|
|
|
|
enum todo_command {
|
|
|
|
/* commands that handle commits */
|
|
|
|
TODO_PICK = 0,
|
|
|
|
TODO_REVERT,
|
|
|
|
TODO_EDIT,
|
|
|
|
TODO_REWORD,
|
|
|
|
TODO_FIXUP,
|
|
|
|
TODO_SQUASH,
|
|
|
|
/* commands that do something else than handling a single commit */
|
|
|
|
TODO_EXEC,
|
|
|
|
TODO_BREAK,
|
|
|
|
TODO_LABEL,
|
|
|
|
TODO_RESET,
|
|
|
|
TODO_MERGE,
|
2022-07-19 18:33:38 +00:00
|
|
|
TODO_UPDATE_REF,
|
2018-12-29 16:03:59 +00:00
|
|
|
/* commands that do nothing but are counted for reporting progress */
|
|
|
|
TODO_NOOP,
|
|
|
|
TODO_DROP,
|
|
|
|
/* comments (not counted for reporting progress) */
|
|
|
|
TODO_COMMENT
|
2018-08-10 16:51:28 +00:00
|
|
|
};
|
|
|
|
|
2018-12-29 16:03:59 +00:00
|
|
|
struct todo_item {
|
|
|
|
enum todo_command command;
|
|
|
|
struct commit *commit;
|
|
|
|
unsigned int flags;
|
|
|
|
int arg_len;
|
2019-01-29 15:01:46 +00:00
|
|
|
/* The offset of the command and its argument in the strbuf */
|
|
|
|
size_t offset_in_buf, arg_offset;
|
2018-12-29 16:03:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct todo_list {
|
|
|
|
struct strbuf buf;
|
|
|
|
struct todo_item *items;
|
|
|
|
int nr, alloc, current;
|
|
|
|
int done_nr, total_nr;
|
|
|
|
};
|
|
|
|
|
2021-09-27 12:54:27 +00:00
|
|
|
#define TODO_LIST_INIT { \
|
|
|
|
.buf = STRBUF_INIT, \
|
|
|
|
}
|
2018-12-29 16:03:59 +00:00
|
|
|
|
|
|
|
int todo_list_parse_insn_buffer(struct repository *r, char *buf,
|
|
|
|
struct todo_list *todo_list);
|
2019-01-29 15:01:48 +00:00
|
|
|
int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list,
|
|
|
|
const char *file, const char *shortrevisions,
|
|
|
|
const char *shortonto, int num, unsigned flags);
|
2018-12-29 16:03:59 +00:00
|
|
|
void todo_list_release(struct todo_list *todo_list);
|
2019-01-29 15:01:46 +00:00
|
|
|
const char *todo_item_get_arg(struct todo_list *todo_list,
|
|
|
|
struct todo_item *item);
|
2018-08-10 16:51:28 +00:00
|
|
|
|
2022-07-19 18:33:41 +00:00
|
|
|
/*
|
|
|
|
* Parse the update-refs file for the current rebase, then remove the
|
|
|
|
* refs that do not appear in the todo_list (and have not had updated
|
|
|
|
* values stored) and add refs that are in the todo_list but not
|
|
|
|
* represented in the update-refs file.
|
|
|
|
*
|
|
|
|
* If there are changes to the update-refs list, then write the new state
|
|
|
|
* to disk.
|
|
|
|
*/
|
|
|
|
void todo_list_filter_update_refs(struct repository *r,
|
|
|
|
struct todo_list *todo_list);
|
|
|
|
|
2017-12-13 11:46:21 +00:00
|
|
|
/* Call this to setup defaults before parsing command line options */
|
|
|
|
void sequencer_init_config(struct replay_opts *opts);
|
2018-11-10 05:48:56 +00:00
|
|
|
int sequencer_pick_revisions(struct repository *repo,
|
|
|
|
struct replay_opts *opts);
|
|
|
|
int sequencer_continue(struct repository *repo, struct replay_opts *opts);
|
2018-11-10 05:48:57 +00:00
|
|
|
int sequencer_rollback(struct repository *repo, struct replay_opts *opts);
|
2019-07-02 09:11:28 +00:00
|
|
|
int sequencer_skip(struct repository *repo, struct replay_opts *opts);
|
2023-02-06 19:08:08 +00:00
|
|
|
void replay_opts_release(struct replay_opts *opts);
|
2016-10-21 12:24:55 +00:00
|
|
|
int sequencer_remove_state(struct replay_opts *opts);
|
2012-01-11 18:15:57 +00:00
|
|
|
|
rebase: reinstate --no-keep-empty
Commit d48e5e21da ("rebase (interactive-backend): make --keep-empty the
default", 2020-02-15) turned --keep-empty (for keeping commits which
start empty) into the default. The logic underpinning that commit was:
1) 'git commit' errors out on the creation of empty commits without an
override flag
2) Once someone determines that the override is worthwhile, it's
annoying and/or harmful to required them to take extra steps in
order to keep such commits around (and to repeat such steps with
every rebase).
While the logic on which the decision was made is sound, the result was
a bit of an overcorrection. Instead of jumping to having --keep-empty
being the default, it jumped to making --keep-empty the only available
behavior. There was a simple workaround, though, which was thought to
be good enough at the time. People could still drop commits which
started empty the same way the could drop any commits: by firing up an
interactive rebase and picking out the commits they didn't want from the
list. However, there are cases where external tools might create enough
empty commits that picking all of them out is painful. As such, having
a flag to automatically remove start-empty commits may be beneficial.
Provide users a way to drop commits which start empty using a flag that
existed for years: --no-keep-empty. Interpret --keep-empty as
countermanding any previous --no-keep-empty, but otherwise leaving
--keep-empty as the default.
This might lead to some slight weirdness since commands like
git rebase --empty=drop --keep-empty
git rebase --empty=keep --no-keep-empty
look really weird despite making perfect sense (the first will drop
commits which become empty, but keep commits that started empty; the
second will keep commits which become empty, but drop commits which
started empty). However, --no-keep-empty was named years ago and we are
predominantly keeping it for backward compatibility; also we suspect it
will only be used rarely since folks already have a simple way to drop
commits they don't want with an interactive rebase.
Reported-by: Bryan Turner <bturner@atlassian.com>
Reported-by: Sami Boukortt <sami@boukortt.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-11 02:44:25 +00:00
|
|
|
#define TODO_LIST_KEEP_EMPTY (1U << 0)
|
2017-12-05 17:52:32 +00:00
|
|
|
#define TODO_LIST_SHORTEN_IDS (1U << 1)
|
2017-12-05 17:52:34 +00:00
|
|
|
#define TODO_LIST_ABBREVIATE_CMDS (1U << 2)
|
2018-04-25 12:29:03 +00:00
|
|
|
#define TODO_LIST_REBASE_MERGES (1U << 3)
|
rebase -i: introduce --rebase-merges=[no-]rebase-cousins
When running `git rebase --rebase-merges` non-interactively with an
ancestor of HEAD as <upstream> (or leaving the todo list unmodified),
we would ideally recreate the exact same commits as before the rebase.
However, if there are commits in the commit range <upstream>.. that do not
have <upstream> as direct ancestor (i.e. if `git log <upstream>..` would
show commits that are omitted by `git log --ancestry-path <upstream>..`),
this is currently not the case: we would turn them into commits that have
<upstream> as direct ancestor.
Let's illustrate that with a diagram:
C
/ \
A - B - E - F
\ /
D
Currently, after running `git rebase -i --rebase-merges B`, the new branch
structure would be (pay particular attention to the commit `D`):
--- C' --
/ \
A - B ------ E' - F'
\ /
D'
This is not really preserving the branch topology from before! The
reason is that the commit `D` does not have `B` as ancestor, and
therefore it gets rebased onto `B`.
This is unintuitive behavior. Even worse, when recreating branch
structure, most use cases would appear to want cousins *not* to be
rebased onto the new base commit. For example, Git for Windows (the
heaviest user of the Git garden shears, which served as the blueprint
for --rebase-merges) frequently merges branches from `next` early, and
these branches certainly do *not* want to be rebased. In the example
above, the desired outcome would look like this:
--- C' --
/ \
A - B ------ E' - F'
\ /
-- D' --
Let's introduce the term "cousins" for such commits ("D" in the
example), and let's not rebase them by default. For hypothetical
use cases where cousins *do* need to be rebased, `git rebase
--rebase=merges=rebase-cousins` needs to be used.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-25 12:29:40 +00:00
|
|
|
/*
|
|
|
|
* When rebasing merges, commits that do have the base commit as ancestor
|
|
|
|
* ("cousins") are *not* rebased onto the new base by default. If those
|
|
|
|
* commits should be rebased onto the new base, this flag needs to be passed.
|
|
|
|
*/
|
|
|
|
#define TODO_LIST_REBASE_COUSINS (1U << 4)
|
2019-01-29 15:01:48 +00:00
|
|
|
#define TODO_LIST_APPEND_TODO_HELP (1U << 5)
|
2019-07-31 15:18:49 +00:00
|
|
|
/*
|
|
|
|
* When generating a script that rebases merges with `--root` *and* with
|
|
|
|
* `--onto`, we do not want to re-generate the root commits.
|
|
|
|
*/
|
|
|
|
#define TODO_LIST_ROOT_WITH_ONTO (1U << 6)
|
2020-04-11 02:44:27 +00:00
|
|
|
#define TODO_LIST_REAPPLY_CHERRY_PICKS (1U << 7)
|
2021-08-30 21:46:02 +00:00
|
|
|
#define TODO_LIST_WARN_SKIPPED_CHERRY_PICKS (1U << 8)
|
2019-01-29 15:01:48 +00:00
|
|
|
|
2019-03-05 19:17:56 +00:00
|
|
|
int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,
|
|
|
|
const char **argv, unsigned flags);
|
2017-07-14 14:44:58 +00:00
|
|
|
|
2018-11-10 05:48:57 +00:00
|
|
|
int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
|
rebase -i: rewrite complete_action() in C
This rewrites complete_action() from shell to C.
A new mode is added to rebase--helper (`--complete-action`), as well as
a new flag (`--autosquash`).
Finally, complete_action() is stripped from git-rebase--interactive.sh.
The original complete_action() would return the code 2 when the todo
list contained no actions. This was a special case for rebase -i and
-p; git-rebase.sh would then apply the autostash, delete the state
directory, and die with the message "Nothing to do". This cleanup is
rewritten in C instead of returning 2. As rebase -i no longer returns
2, the comment describing this behaviour in git-rebase.sh is updated to
reflect this change.
The message "Nothing to do" is now printed with error(), and so becomes
"error: nothing to do". Some tests in t3404 check this value, so they
are updated to fit this change.
The first check might seem useless as we write "noop" to the todo list
if it is empty. Actually, the todo list might contain commented
commands (ie. empty commits). In this case, complete_action() won’t
write "noop", and will abort without starting the editor.
Signed-off-by: Alban Gruin <alban.gruin@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-28 12:10:36 +00:00
|
|
|
const char *shortrevisions, const char *onto_name,
|
2020-11-04 15:29:38 +00:00
|
|
|
struct commit *onto, const struct object_id *orig_head,
|
|
|
|
struct string_list *commands, unsigned autosquash,
|
2022-07-19 18:33:39 +00:00
|
|
|
unsigned update_refs,
|
2020-11-04 15:29:38 +00:00
|
|
|
struct todo_list *todo_list);
|
2019-03-05 19:17:59 +00:00
|
|
|
int todo_list_rearrange_squash(struct todo_list *todo_list);
|
2017-07-14 14:45:11 +00:00
|
|
|
|
2018-08-23 00:50:51 +00:00
|
|
|
/*
|
|
|
|
* Append a signoff to the commit message in "msgbuf". The ignore_footer
|
|
|
|
* parameter specifies the number of bytes at the end of msgbuf that should
|
|
|
|
* not be considered at all. I.e., they are not checked for existing trailers,
|
|
|
|
* and the new signoff will be spliced into the buffer before those bytes.
|
|
|
|
*/
|
|
|
|
void append_signoff(struct strbuf *msgbuf, size_t ignore_footer, unsigned flag);
|
|
|
|
|
2019-04-17 10:23:30 +00:00
|
|
|
void append_conflicts_hint(struct index_state *istate,
|
|
|
|
struct strbuf *msgbuf, enum commit_msg_cleanup_mode cleanup_mode);
|
2019-04-17 10:23:25 +00:00
|
|
|
enum commit_msg_cleanup_mode get_cleanup_mode(const char *cleanup_arg,
|
|
|
|
int use_editor);
|
|
|
|
|
|
|
|
void cleanup_message(struct strbuf *msgbuf,
|
|
|
|
enum commit_msg_cleanup_mode cleanup_mode, int verbose);
|
|
|
|
|
2017-11-10 11:09:42 +00:00
|
|
|
int message_is_empty(const struct strbuf *sb,
|
|
|
|
enum commit_msg_cleanup_mode cleanup_mode);
|
|
|
|
int template_untouched(const struct strbuf *sb, const char *template_file,
|
|
|
|
enum commit_msg_cleanup_mode cleanup_mode);
|
2017-11-17 11:34:47 +00:00
|
|
|
int update_head_with_reflog(const struct commit *old_head,
|
|
|
|
const struct object_id *new_head,
|
|
|
|
const char *action, const struct strbuf *msg,
|
|
|
|
struct strbuf *err);
|
2019-01-12 02:13:23 +00:00
|
|
|
void commit_post_rewrite(struct repository *r,
|
|
|
|
const struct commit *current_head,
|
2017-11-17 11:34:48 +00:00
|
|
|
const struct object_id *new_head);
|
2012-09-14 06:52:03 +00:00
|
|
|
|
2022-01-26 13:05:44 +00:00
|
|
|
void create_autostash(struct repository *r, const char *path);
|
2024-01-19 10:40:15 +00:00
|
|
|
void create_autostash_ref(struct repository *r, const char *refname);
|
2020-04-07 14:28:05 +00:00
|
|
|
int save_autostash(const char *path);
|
2024-01-19 10:40:15 +00:00
|
|
|
int save_autostash_ref(struct repository *r, const char *refname);
|
2020-04-07 14:27:58 +00:00
|
|
|
int apply_autostash(const char *path);
|
2020-04-07 14:28:06 +00:00
|
|
|
int apply_autostash_oid(const char *stash_oid);
|
2024-01-19 10:40:15 +00:00
|
|
|
int apply_autostash_ref(struct repository *r, const char *refname);
|
2020-04-07 14:27:58 +00:00
|
|
|
|
2017-11-24 11:07:54 +00:00
|
|
|
#define SUMMARY_INITIAL_COMMIT (1 << 0)
|
|
|
|
#define SUMMARY_SHOW_AUTHOR_DATE (1 << 1)
|
2018-11-10 05:48:56 +00:00
|
|
|
void print_commit_summary(struct repository *repo,
|
|
|
|
const char *prefix,
|
|
|
|
const struct object_id *oid,
|
2017-11-24 11:07:54 +00:00
|
|
|
unsigned int flags);
|
2018-10-31 10:15:55 +00:00
|
|
|
|
2020-04-07 14:27:54 +00:00
|
|
|
#define READ_ONELINER_SKIP_IF_EMPTY (1 << 0)
|
|
|
|
#define READ_ONELINER_WARN_MISSING (1 << 1)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reads a file that was presumably written by a shell script, i.e. with an
|
|
|
|
* end-of-line marker that needs to be stripped.
|
|
|
|
*
|
|
|
|
* Note that only the last end-of-line marker is stripped, consistent with the
|
|
|
|
* behavior of "$(cat path)" in a shell script.
|
|
|
|
*
|
|
|
|
* Returns 1 if the file was read, 0 if it could not be read or does not exist.
|
|
|
|
*/
|
|
|
|
int read_oneliner(struct strbuf *buf,
|
|
|
|
const char *path, unsigned flags);
|
2018-10-31 10:15:55 +00:00
|
|
|
int read_author_script(const char *path, char **name, char **email, char **date,
|
|
|
|
int allow_missing);
|
2018-08-28 12:10:40 +00:00
|
|
|
int write_basic_state(struct replay_opts *opts, const char *head_name,
|
2020-11-04 15:29:39 +00:00
|
|
|
struct commit *onto, const struct object_id *orig_head);
|
2019-07-09 22:25:44 +00:00
|
|
|
void sequencer_post_commit_cleanup(struct repository *r, int verbose);
|
2019-04-16 10:18:42 +00:00
|
|
|
int sequencer_get_last_command(struct repository* r,
|
|
|
|
enum replay_action *action);
|
2019-12-06 16:06:11 +00:00
|
|
|
int sequencer_determine_whence(struct repository *r, enum commit_whence *whence);
|
2022-07-19 18:33:35 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Append the set of ref-OID pairs that are currently stored for the 'git
|
|
|
|
* rebase --update-refs' feature if such a rebase is currently happening.
|
|
|
|
*
|
|
|
|
* Localized to a worktree's git dir.
|
|
|
|
*/
|
|
|
|
int sequencer_get_update_refs_state(const char *wt_dir, struct string_list *refs);
|
|
|
|
|
2019-10-15 10:25:30 +00:00
|
|
|
#endif /* SEQUENCER_H */
|