[PATCH v5 0/6][Outreachy] commit: Implementation of "amend!" commit
- From
Charvi Mendiratta <charvi077@gmail.com>
- Date
- Mar 13, 2021, 13:40 UTC
- Message-ID
- <20210313134012.20658-1-charvi077@gmail.com>
- In-Reply-To
- <20210310194306.32565-1-charvi077@gmail.com>
This patch series teaches `git commit --fixup` to create "amend!" commit as an alternative that works with `git rebase --autosquash`. It allows to fixup both the content and the commit message of the specified commit. Here we add two suboptions to the `--fixup`, first `amend` suboption that creates an "amend!" commit. It takes the staged changes and also allows to edit the commit message of the commit we are fixing. Example usuage: git commit --fixup=amend:<commit>
Secondly, `reword` suboption that creates an empty "amend!" commit i.e it ignores the staged changes and only allows to reword/edit the commit message of the commit we are fixing. `--fixup=reword:<commit>` is a short-hand of `--fixup=amend:<commit> --only`. Example usuage: git commit --fixup=reword:<commit>
** This work is rebased on the top of cm/rebase-i-updates.
Charvi Mendiratta (6): sequencer: export and rename subject_length() commit: add amend suboption to --fixup to create amend! commit commit: add a reword suboption to --fixup t7500: add tests for --fixup=[amend|reword] options t3437: use --fixup with options to create amend! commit doc/git-commit: add documentation for fixup=[amend|reword] options
Documentation/git-commit.txt | 45 +++++- Documentation/git-rebase.txt | 21 +-- builtin/commit.c | 126 +++++++++++++++-- commit.c | 14 ++ commit.h | 3 + sequencer.c | 16 +-- t/t3437-rebase-fixup-options.sh | 30 +--- t/t7500-commit-template-squash-signoff.sh | 159 ++++++++++++++++++++++ 8 files changed, 346 insertions(+), 68 deletions(-)
Range-diff against v4:
-: ---------- > 1: a2e89540ec sequencer: export and rename subject_length()
1: 492ab8ec08 ! 2: be2808a255 commit: add amend suboption to --fixup to create amend! commit
@@ builtin/commit.c: static void adjust_comment_line_char(const struct strbuf *sb)
comment_line_char = *p;
} -+static int prepare_amend_commit(struct commit *commit, struct strbuf *sb,
-+ struct pretty_print_context *ctx) {
-+
++static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
++ struct pretty_print_context *ctx)
++{
+ const char *buffer, *subject, *fmt;
+
+ buffer = get_commit_buffer(commit, NULL);
@@ builtin/commit.c: static void adjust_comment_line_char(const struct strbuf *sb)
+ fmt = starts_with(subject, "amend!") ? "%b" : "%B";
+ format_commit_message(commit, fmt, sb, ctx);
+ unuse_commit_buffer(commit, buffer);
-+ return 0;
+}
+
static int prepare_to_commit(const char *index_file, const char *prefix,
@@ builtin/commit.c: static int prepare_to_commit(const char *index_file, const cha
struct pretty_print_context ctx = {0};
struct commit *commit;
- commit = lookup_commit_reference_by_name(fixup_message);
-+ char *fmt = xstrfmt("%s! %%s\n\n", fixup_prefix);
++ char *fmt;
+ commit = lookup_commit_reference_by_name(fixup_commit);
if (!commit)
- die(_("could not lookup commit %s"), fixup_message);
@@ builtin/commit.c: static int prepare_to_commit(const char *index_file, const cha
- &sb, &ctx);
- if (have_option_m)
- strbuf_addbuf(&sb, &message);
++ fmt = xstrfmt("%s! %%s\n\n", fixup_prefix);
+ format_commit_message(commit, fmt, &sb, &ctx);
+ free(fmt);
hook_arg1 = "message";
@@ builtin/commit.c: static void finalize_deferred_config(struct wt_status *s)
} +/* returns the length of intial segment of alpha characters only */
-+static size_t get_alpha_len(char *fixup_message) {
++static size_t skip_suboption(char *fixup_message) {
+ const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
+ return strspn(fixup_message, alphas);
+}
@@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *ar
+
+ if (fixup_message) {
+ /*
-+ * To check if fixup_message that contains ':' is a commit
-+ * reference for example: --fixup="HEAD^{/^area: string}" or
-+ * a suboption of `--fixup`.
++ * We limit --fixup's suboptions to only alpha characters.
++ * If the first character after a run of alpha is colon,
++ * then the part before the colon may be a known suboption
++ * name `amend` or a misspelt suboption name. In this case,
++ * we treat it as --fixup=<suboption>:<arg>.
+ *
-+ * As `amend` suboption contains only alpha character.
-+ * So check if first non alpha character in fixup_message
-+ * is ':'.
++ * Otherwise, we are dealing with --fixup=<commit>.
+ */
-+ size_t len = get_alpha_len(fixup_message);
++ size_t len = skip_suboption(fixup_message);
+ if (len && fixup_message[len] == ':') {
+ fixup_message[len++] = '\0';
+ fixup_commit = fixup_message + len;
2: a20b85c3a1 ! 3: f6217338c1 commit: add a reword suboption to --fixup
@@ builtin/commit.c: static void finalize_deferred_config(struct wt_status *s)
+}
+
/* returns the length of intial segment of alpha characters only */
- static size_t get_alpha_len(char *fixup_message) {
+ static size_t skip_suboption(char *fixup_message) {
const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
@@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *argv[],
- * reference for example: --fixup="HEAD^{/^area: string}" or
- * a suboption of `--fixup`.
+ * We limit --fixup's suboptions to only alpha characters.
+ * If the first character after a run of alpha is colon,
+ * then the part before the colon may be a known suboption
+- * name `amend` or a misspelt suboption name. In this case,
+- * we treat it as --fixup=<suboption>:<arg>.
++ * name like `amend` or `reword`, or a misspelt suboption
++ * name. In either case, we treat it as
++ * --fixup=<suboption>:<arg>.
*
-- * As `amend` suboption contains only alpha character.
-- * So check if first non alpha character in fixup_message
-- * is ':'.
-+ * As `amend`/`reword` suboptions contains only alpha
-+ * characters. So check if first non alpha character
-+ * in fixup_message is ':'.
+ * Otherwise, we are dealing with --fixup=<commit>.
*/
- size_t len = get_alpha_len(fixup_message);
+@@ builtin/commit.c: static int parse_and_validate_options(int argc, const char *argv[],
if (len && fixup_message[len] == ':') {
fixup_message[len++] = '\0';
fixup_commit = fixup_message + len;
3: 41297d7e8e = 4: 1a127dc0b3 t7500: add tests for --fixup=[amend|reword] options
4: 7ae75dc27d = 5: be6f4fa0d1 t3437: use --fixup with options to create amend! commit
5: 533fed36ca ! 6: 79c098df2c doc/git-commit: add documentation for fixup=[amend|reword] options
@@ Commit message
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Mentored-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Helped-by: Junio C Hamano <gitster@pobox.com>
- Helped-by: Eric Sunshine <sunshine@sunshineco.com>
+ Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Charvi Mendiratta <charvi077@gmail.com> ## Documentation/git-commit.txt ##
@@ Documentation/git-commit.txt: OPTIONS
- commit with a prefix of "fixup! ". See linkgit:git-rebase[1]
- for details.
+--fixup=[(amend|reword):]<commit>::
-+ Construct a new commit for use with `rebase --autosquash`,
-+ which fixes the specified commit. The plain form
-+ `--fixup=<commit>` creates a "fixup!" commit, that allows
-+ to fixup only the content of the specified commit and leave
-+ it's commit log message untouched. When used with `amend:`
-+ or `reword:`, it creates "amend!" commit that is like "fixup!"
-+ commit but it allows to fixup both the content and the commit
-+ log message of the specified commit. The commit log message of
-+ the specified commit is fixed implicitly by replacing it with
-+ the "amend!" commit's message body upon `rebase --autosquash`.
++ Create a new commit which "fixes up" `<commit>` when applied with
++ `git rebase --autosquash`. Plain `--fixup=<commit>` creates a
++ "fixup!" commit which changes the content of `<commit>` but leaves
++ its log message untouched. `--fixup=amend:<commit>` is similar but
++ creates an "amend!" commit which also replaces the log message of
++ `<commit>` with the log message of the "amend!" commit.
++ `--fixup=reword:<commit>` creates an "amend!" commit which
++ replaces the log message of `<commit>` with its own log message
++ but makes no changes to the content of `<commit>`.
++
-+The resulting "fixup!" commit message will be the subject line
-+from the specified commit with a prefix of "fixup!". Can be used
-+with additional commit message option `-m`.
++The commit created by plain `--fixup=<commit>` has a subject
++composed of "fixup!" followed by the subject line from <commit>,
++and is recognized specially by `git rebase --autosquash`. The `-m`
++option may be used to supplement the log message of the created
++commit, but the additional commentary will be thrown away once the
++"fixup!" commit is squashed into `<commit>` by
++`git rebase --autosquash`.
++
-+The `--fixup=amend:<commit>` form creates an "amend!" commit where
-+its commit message subject will be the subject line from the
-+specified commit with a prefix of "amend!" and the message body
-+will be commit log message of the specified commit. It also invokes
-+an editor seeded with the log message of the "amend!" commit to
-+allow to edit further. It refuses to create "amend!" commit if it's
-+commit message body is empty unless used with the
-+`--allow-empty-message` option.
++The commit created by `--fixup=amend:<commit>` is similar but its
++subject is instead prefixed with "amend!". The log message of
++<commit> is copied into the log message of the "amend!" commit and
++opened in an editor so it can be refined. When `git rebase
++--autosquash` squashes the "amend!" commit into `<commit>`, the
++log message of `<commit>` is replaced by the refined log message
++from the "amend!" commit. It is an error for the "amend!" commit's
++log message to be empty unless `--allow-empty-message` is
++specified.
++
-+The `--fixup=reword:<commit>` aliases `--fixup=amend:<commit> --only`
-+and it also creates an "amend!" commit, but here it records the same
-+tree as `HEAD`, i.e. it does not take any staged changes and only allows
-+to fixup the commit message of the specified commit. It will reword the
-+specified commit when it is rebased with `--autosquash`.
++`--fixup=reword:<commit>` is shorthand for `--fixup=amend:<commit>
++--only`. It creates an "amend!" commit with only a log message
++(ignoring any changes staged in the index). When squashed by `git
++rebase --autosquash`, it replaces the log message of `<commit>`
++without making any other changes.
++
-+Also, after fixing the commit using `--fixup`, with or without option
-+and rebased with `--autosquash`, the authorship of the original commit
-+remains unchanged. See linkgit:git-rebase[1] for details.
++Neither "fixup!" nor "amend!" commits change authorship of
++`<commit>` when applied by `git rebase --autosquash`.
++See linkgit:git-rebase[1] for details. --squash=<commit>::
Construct a commit message for use with `rebase --autosquash`.
--
2.29.0.rc1