From: Jacob Stopak <jacob@initialcommit.io>
To: git@vger.kernel.org
Cc: Jacob Stopak <jacob@initialcommit.io>
Subject: [RFC PATCH 4/5] add: add -t, --table flag for visual dry runs
Date: Fri, 20 Oct 2023 11:39:46 -0700 [thread overview]
Message-ID: <20231020183947.463882-5-jacob@initialcommit.io> (raw)
In-Reply-To: <20231020183947.463882-1-jacob@initialcommit.io>
Signed-off-by: Jacob Stopak <jacob@initialcommit.io>
---
builtin/add.c | 46 ++++++++++++++++++------
builtin/commit.c | 2 +-
read-cache-ll.h | 9 ++++-
read-cache.c | 32 ++++++++++++++---
table.c | 92 +++++++++++++++++++++++++++++++++++++++++++-----
wt-status.c | 1 +
wt-status.h | 1 +
7 files changed, 157 insertions(+), 26 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index c27254a5cd..35ea1deda5 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -27,6 +27,7 @@
#include "strvec.h"
#include "submodule.h"
#include "add-interactive.h"
+#include "wt-status.h"
static const char * const builtin_add_usage[] = {
N_("git add [<options>] [--] <pathspec>..."),
@@ -221,7 +222,7 @@ N_("The following paths are ignored by one of your .gitignore files:\n");
static int verbose, show_only, ignored_too, refresh_only;
static int ignore_add_errors, intent_to_add, ignore_missing;
-static int warn_on_embedded_repo = 1;
+static int table_format, warn_on_embedded_repo = 1;
#define ADDREMOVE_DEFAULT 1
static int addremove = ADDREMOVE_DEFAULT;
@@ -264,6 +265,8 @@ static struct option builtin_add_options[] = {
N_("warn when adding an embedded repository")),
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
+ OPT_SET_INT('t', "table", &table_format,
+ N_("show status in table format"), STATUS_FORMAT_TABLE),
OPT_END(),
};
@@ -322,7 +325,7 @@ static void check_embedded_repo(const char *path)
strbuf_release(&name);
}
-static int add_files(struct dir_struct *dir, int flags)
+static int add_files(struct dir_struct *dir, int flags, struct wt_status *status)
{
int i, exit_status = 0;
struct string_list matched_sparse_paths = STRING_LIST_INIT_NODUP;
@@ -345,7 +348,7 @@ static int add_files(struct dir_struct *dir, int flags)
dir->entries[i]->name);
continue;
}
- if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
+ if (add_file_to_index_with_status(&the_index, dir->entries[i]->name, flags, status)) {
if (!ignore_add_errors)
die(_("adding files failed"));
exit_status = 1;
@@ -374,6 +377,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
int require_pathspec;
char *seen = NULL;
struct lock_file lock_file = LOCK_INIT;
+ struct wt_status status;
+ unsigned int progress_flag = 0;
git_config(add_config, NULL);
@@ -459,7 +464,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
(intent_to_add ? ADD_CACHE_INTENT : 0) |
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
(!(addremove || take_worktree_changes)
- ? ADD_CACHE_IGNORE_REMOVAL : 0));
+ ? ADD_CACHE_IGNORE_REMOVAL : 0) |
+ (table_format ? ADD_CACHE_FORMAT_TABLE : 0));
if (repo_read_index_preload(the_repository, &pathspec, 0) < 0)
die(_("index file corrupt"));
@@ -551,15 +557,35 @@ int cmd_add(int argc, const char **argv, const char *prefix)
begin_odb_transaction();
- if (add_renormalize)
+ if (show_only && table_format) {
+ /* Prepare index and populate status */
+ wt_status_prepare(the_repository, &status);
+ git_config(git_default_config, &status);
+ repo_read_index(the_repository);
+ refresh_index(&the_index,
+ REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
+ &status.pathspec, NULL, NULL);
+ status.status_format = STATUS_FORMAT_TABLE;
+ status.show_branch = 0;
+ }
+
+ if (add_renormalize) {
exit_status |= renormalize_tracked_files(&pathspec, flags);
- else
- exit_status |= add_files_to_cache(the_repository, prefix,
+ } else {
+ exit_status |= add_files_to_cache_with_status(the_repository, prefix,
&pathspec, include_sparse,
- flags);
+ flags, &status);
+ }
- if (add_new_files)
- exit_status |= add_files(&dir, flags);
+ if (add_new_files) {
+ exit_status |= add_files(&dir, flags, &status);
+ }
+
+ if (show_only && table_format) {
+ wt_status_collect(&status);
+ wt_status_print(&status);
+ wt_status_collect_free_buffers(&status);
+ }
if (chmod_arg && pathspec.nr)
exit_status |= chmod_pathspec(&pathspec, chmod_arg[0], show_only);
diff --git a/builtin/commit.c b/builtin/commit.c
index 4338896dbf..33b15ef96e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -310,7 +310,7 @@ static void add_remove_files(struct string_list *list)
continue;
if (!lstat(p->string, &st)) {
- if (add_to_index(&the_index, p->string, &st, 0))
+ if (add_file_to_index(&the_index, p->string, 0))
die(_("updating files failed"));
} else
remove_file_from_index(&the_index, p->string);
diff --git a/read-cache-ll.h b/read-cache-ll.h
index 9a1a7edc5a..b1cee2c7ee 100644
--- a/read-cache-ll.h
+++ b/read-cache-ll.h
@@ -4,6 +4,7 @@
#include "hash-ll.h"
#include "hashmap.h"
#include "statinfo.h"
+#include "wt-status.h"
/*
* Basic data structures for the directory cache
@@ -395,6 +396,7 @@ int remove_file_from_index(struct index_state *, const char *path);
#define ADD_CACHE_IGNORE_ERRORS 4
#define ADD_CACHE_IGNORE_REMOVAL 8
#define ADD_CACHE_INTENT 16
+#define ADD_CACHE_FORMAT_TABLE 32
/*
* These two are used to add the contents of the file at path
* to the index, marking the working tree up-to-date by storing
@@ -404,7 +406,8 @@ int remove_file_from_index(struct index_state *, const char *path);
* the latter will do necessary lstat(2) internally before
* calling the former.
*/
-int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
+int add_to_index(struct index_state *, const char *path, struct stat *, int flags, struct wt_status *status);
+int add_file_to_index_with_status(struct index_state *, const char *path, int flags, struct wt_status *status);
int add_file_to_index(struct index_state *, const char *path, int flags);
int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
@@ -475,6 +478,10 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
const struct pathspec *pathspec, int include_sparse,
int flags);
+int add_files_to_cache_with_status(struct repository *repo, const char *prefix,
+ const struct pathspec *pathspec, int include_sparse,
+ int flags, struct wt_status *status);
+
void overlay_tree_on_index(struct index_state *istate,
const char *tree_name, const char *prefix);
diff --git a/read-cache.c b/read-cache.c
index 080bd39713..e777cdb210 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -45,6 +45,8 @@
#include "csum-file.h"
#include "promisor-remote.h"
#include "hook.h"
+#include "wt-status.h"
+#include "string-list.h"
/* Mask for the name length in ce_flags in the on-disk index */
@@ -664,7 +666,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
oidcpy(&ce->oid, &oid);
}
-int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
+int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags, struct wt_status *status)
{
int namelen, was_same;
mode_t st_mode = st->st_mode;
@@ -672,6 +674,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE|CE_MATCH_RACY_IS_DIRTY;
int verbose = flags & (ADD_CACHE_VERBOSE | ADD_CACHE_PRETEND);
int pretend = flags & ADD_CACHE_PRETEND;
+ int table = flags & ADD_CACHE_FORMAT_TABLE;
int intent_only = flags & ADD_CACHE_INTENT;
int add_option = (ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|
(intent_only ? ADD_CACHE_NEW_ONLY : 0));
@@ -760,17 +763,26 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
discard_cache_entry(ce);
return error(_("unable to add '%s' to index"), path);
}
- if (verbose && !was_same)
+ if (verbose && !was_same && !table)
printf("add '%s'\n", path);
+ if (table && pretend && !was_same) {
+ string_list_insert(&status->dry_run_added, path);
+ }
return 0;
}
-int add_file_to_index(struct index_state *istate, const char *path, int flags)
+int add_file_to_index_with_status(struct index_state *istate, const char *path, int flags, struct wt_status *status)
{
struct stat st;
if (lstat(path, &st))
die_errno(_("unable to stat '%s'"), path);
- return add_to_index(istate, path, &st, flags);
+ return add_to_index(istate, path, &st, flags, status);
+}
+
+int add_file_to_index(struct index_state *istate, const char *path, int flags)
+{
+ struct wt_status status;
+ return add_file_to_index_with_status(istate, path, flags, &status);
}
struct cache_entry *make_empty_cache_entry(struct index_state *istate, size_t len)
@@ -3872,6 +3884,7 @@ struct update_callback_data {
int include_sparse;
int flags;
int add_errors;
+ struct wt_status *status;
};
static int fix_unmerged_status(struct diff_filepair *p,
@@ -3914,7 +3927,7 @@ static void update_callback(struct diff_queue_struct *q,
die(_("unexpected diff status %c"), p->status);
case DIFF_STATUS_MODIFIED:
case DIFF_STATUS_TYPE_CHANGED:
- if (add_file_to_index(data->index, path, data->flags)) {
+ if (add_file_to_index_with_status(data->index, path, data->flags, data->status)) {
if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
die(_("updating files failed"));
data->add_errors++;
@@ -3935,6 +3948,14 @@ static void update_callback(struct diff_queue_struct *q,
int add_files_to_cache(struct repository *repo, const char *prefix,
const struct pathspec *pathspec, int include_sparse,
int flags)
+{
+ struct wt_status status;
+ return add_files_to_cache_with_status(repo, prefix, pathspec, include_sparse, flags, &status);
+}
+
+int add_files_to_cache_with_status(struct repository *repo, const char *prefix,
+ const struct pathspec *pathspec, int include_sparse,
+ int flags, struct wt_status *status)
{
struct update_callback_data data;
struct rev_info rev;
@@ -3943,6 +3964,7 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
data.index = repo->index;
data.include_sparse = include_sparse;
data.flags = flags;
+ data.status = status;
repo_init_revisions(repo, &rev, prefix);
setup_revisions(0, NULL, &rev, NULL);
diff --git a/table.c b/table.c
index 73751339da..a6fc660fec 100644
--- a/table.c
+++ b/table.c
@@ -65,18 +65,53 @@ static void build_table_entry(struct strbuf *buf, char *entry, int cols)
strbuf_addchars(buf, ' ', (cols / 3 - len - 1) / 2);
}
-static void print_table_body_line(struct strbuf *buf1, struct strbuf *buf2, struct strbuf *buf3, struct wt_status *s)
+static void add_arrow_to_entry(struct strbuf *buf, int add_after_entry)
+{
+ struct strbuf empty = STRBUF_INIT;
+ struct strbuf trimmed = STRBUF_INIT;
+ struct strbuf holder = STRBUF_INIT;
+ int len = strlen(buf->buf);
+
+ strbuf_addstr(&trimmed, buf->buf);
+ strbuf_trim(&trimmed);
+
+ if (!strbuf_cmp(&trimmed, &empty) && !add_after_entry) {
+ strbuf_reset(buf);
+ strbuf_addchars(buf, '-', len + 1);
+ } else if (add_after_entry) {
+ strbuf_rtrim(buf);
+ strbuf_addchars(buf, ' ', 1);
+ strbuf_addchars(buf, '-', len - strlen(buf->buf) + 1);
+ } else if (!add_after_entry) {
+ strbuf_ltrim(buf);
+ strbuf_addchars(&holder, '-', len - strlen(buf->buf) - 2);
+ strbuf_addchars(&holder, '>', 1);
+ strbuf_addchars(&holder, ' ', 1);
+ strbuf_addstr(&holder, buf->buf);
+ strbuf_reset(buf);
+ strbuf_addstr(buf, holder.buf);
+ }
+}
+
+static void print_table_body_line(struct strbuf *buf1, struct strbuf *buf2, struct strbuf *buf3, struct wt_status *s, int hide_pipe)
{
printf(_("|"));
color_fprintf(s->fp, color(WT_STATUS_UNTRACKED, s), "%s", buf1->buf);
- printf(_("|"));
+ if (hide_pipe != 1 && hide_pipe != 3)
+ printf(_("|"));
color_fprintf(s->fp, color(WT_STATUS_CHANGED, s), "%s", buf2->buf);
- printf(_("|"));
+ if (hide_pipe != 2 && hide_pipe != 3)
+ printf(_("|"));
color_fprintf(s->fp, color(WT_STATUS_UPDATED, s), "%s", buf3->buf);
printf(_("|\n"));
}
-void build_and_draw_status_table(struct wt_status *s, int add_advice)
+static void print_table_body_line_(struct strbuf *buf1, struct strbuf *buf2, struct strbuf *buf3, struct wt_status *s)
+{
+ print_table_body_line(buf1, buf2, buf3, s, 0);
+}
+
+void build_and_draw_status_table(struct wt_status *s, int advice)
{
struct winsize w;
int cols;
@@ -84,7 +119,7 @@ void build_and_draw_status_table(struct wt_status *s, int add_advice)
struct strbuf table_col_entry_1 = STRBUF_INIT;
struct strbuf table_col_entry_2 = STRBUF_INIT;
struct strbuf table_col_entry_3 = STRBUF_INIT;
- struct string_list_item *item;
+ struct string_list_item *item, *item2;
/* Get terminal width */
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
@@ -104,7 +139,7 @@ void build_and_draw_status_table(struct wt_status *s, int add_advice)
printf(_("%s\n"), table_border.buf);
printf(_("|%s|%s|%s|\n"), table_col_entry_1.buf, table_col_entry_2.buf, table_col_entry_3.buf);
- if (add_advice) {
+ if (advice) {
build_table_entry(&table_col_entry_1, "(stage: git add <file>)", cols);
build_table_entry(&table_col_entry_2, "(stage: git add <file>)", cols);
build_table_entry(&table_col_entry_3, "(unstage: git restore --staged <file>)", cols);
@@ -122,14 +157,38 @@ void build_and_draw_status_table(struct wt_status *s, int add_advice)
/* Draw table body */
for_each_string_list_item(item, &s->untracked) {
- build_table_entry(&table_col_entry_1, item->string, cols);
+ struct strbuf buf_1 = STRBUF_INIT;
+ struct strbuf buf_2 = STRBUF_INIT;
+ int is_arrow = 0;
+ strbuf_addstr(&buf_1, item->string);
+ build_table_entry(&table_col_entry_1, buf_1.buf, cols);
build_table_entry(&table_col_entry_2, "", cols);
build_table_entry(&table_col_entry_3, "", cols);
- print_table_body_line(&table_col_entry_1, &table_col_entry_2, &table_col_entry_3, s);
+
+ for_each_string_list_item(item2, &s->dry_run_added) {
+ strbuf_reset(&buf_2);
+ strbuf_addstr(&buf_2, item2->string);
+ if (!strbuf_cmp(&buf_1, &buf_2)) {
+ build_table_entry(&table_col_entry_3, buf_1.buf, cols);
+ add_arrow_to_entry(&table_col_entry_1, 1);
+ add_arrow_to_entry(&table_col_entry_2, 0);
+ add_arrow_to_entry(&table_col_entry_3, 0);
+ is_arrow = 1;
+ }
+ }
+
+ if (!is_arrow)
+ print_table_body_line_(&table_col_entry_1, &table_col_entry_2, &table_col_entry_3, s);
+ else
+ print_table_body_line(&table_col_entry_1, &table_col_entry_2, &table_col_entry_3, s, 3);
}
for_each_string_list_item(item, &s->change) {
struct wt_status_change_data *d = item->util;
+ struct strbuf buf_1 = STRBUF_INIT;
+ struct strbuf buf_2 = STRBUF_INIT;
+ int is_arrow = 0;
+ strbuf_addstr(&buf_1, item->string);
if (d->worktree_status && d->index_status) {
build_table_entry(&table_col_entry_1, "", cols);
build_table_entry(&table_col_entry_2, item->string, cols);
@@ -138,12 +197,27 @@ void build_and_draw_status_table(struct wt_status *s, int add_advice)
build_table_entry(&table_col_entry_1, "", cols);
build_table_entry(&table_col_entry_2, item->string, cols);
build_table_entry(&table_col_entry_3, "", cols);
+
+ for_each_string_list_item(item2, &s->dry_run_added) {
+ strbuf_reset(&buf_2);
+ strbuf_addstr(&buf_2, item2->string);
+ if (!strbuf_cmp(&buf_1, &buf_2)) {
+ build_table_entry(&table_col_entry_3, buf_1.buf, cols);
+ add_arrow_to_entry(&table_col_entry_2, 1);
+ add_arrow_to_entry(&table_col_entry_3, 0);
+ is_arrow = 1;
+ }
+ }
} else if (d->index_status) {
build_table_entry(&table_col_entry_1, "", cols);
build_table_entry(&table_col_entry_2, "", cols);
build_table_entry(&table_col_entry_3, item->string, cols);
}
- print_table_body_line(&table_col_entry_1, &table_col_entry_2, &table_col_entry_3, s);
+
+ if (!is_arrow)
+ print_table_body_line_(&table_col_entry_1, &table_col_entry_2, &table_col_entry_3, s);
+ else
+ print_table_body_line(&table_col_entry_1, &table_col_entry_2, &table_col_entry_3, s, 2);
}
if (!s->untracked.nr && !s->change.nr) {
diff --git a/wt-status.c b/wt-status.c
index 62731859fe..975cfc01a5 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -153,6 +153,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)
s->change.strdup_strings = 1;
s->untracked.strdup_strings = 1;
s->ignored.strdup_strings = 1;
+ s->dry_run_added.strdup_strings = 1;
s->show_branch = -1; /* unspecified */
s->show_stash = 0;
s->ahead_behind_flags = AHEAD_BEHIND_UNSPECIFIED;
diff --git a/wt-status.h b/wt-status.h
index 70a3b7a2e4..5d29c058c1 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -142,6 +142,7 @@ struct wt_status {
struct string_list change;
struct string_list untracked;
struct string_list ignored;
+ struct string_list dry_run_added;
uint32_t untracked_in_ms;
};
--
2.42.0.402.gbe8243af7b.dirty
next prev parent reply other threads:[~2023-10-20 18:39 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-20 18:39 [RFC PATCH 0/5] Introduce -t, --table for status/add commands Jacob Stopak
2023-10-20 18:39 ` [RFC PATCH 1/5] status: introduce -t, --table flag Jacob Stopak
2023-10-20 18:39 ` [RFC PATCH 2/5] status: handle long paths with " Jacob Stopak
2023-10-20 18:39 ` [RFC PATCH 3/5] status: add advice arg for " Jacob Stopak
2023-10-20 18:39 ` Jacob Stopak [this message]
2023-10-20 18:39 ` [RFC PATCH 5/5] add: set unique color for -t, --table arrows Jacob Stopak
2023-10-20 18:48 ` [RFC PATCH 0/5] Introduce -t, --table for status/add commands Dragan Simic
2023-10-20 21:48 ` Jacob Stopak
2023-10-20 23:02 ` Dragan Simic
2023-10-20 23:28 ` Junio C Hamano
2023-10-22 6:04 ` Jacob Stopak
2023-10-22 6:52 ` Dragan Simic
2023-10-22 5:52 ` Jacob Stopak
2023-10-22 6:38 ` Dragan Simic
2023-10-22 10:30 ` Oswald Buddenhagen
2023-10-22 12:55 ` Dragan Simic
2023-10-23 10:52 ` Oswald Buddenhagen
2023-10-23 14:34 ` Dragan Simic
2023-10-23 17:30 ` Jacob Stopak
2023-10-23 17:59 ` Dragan Simic
2023-10-23 18:16 ` Oswald Buddenhagen
2023-10-23 19:29 ` Jacob Stopak
2023-10-23 20:19 ` Oswald Buddenhagen
2023-10-23 20:51 ` Dragan Simic
2023-10-23 21:14 ` Oswald Buddenhagen
2023-10-23 21:19 ` Dragan Simic
2023-10-23 23:17 ` Jacob Stopak
2023-10-24 1:10 ` Dragan Simic
2023-10-24 2:03 ` Junio C Hamano
2023-10-24 2:21 ` Dragan Simic
2024-01-05 19:14 ` Dragan Simic
2024-01-06 4:44 ` Jacob Stopak
2024-01-06 7:06 ` Dragan Simic
2023-10-23 20:29 ` Dragan Simic
2023-10-23 19:01 ` Junio C Hamano
2023-10-23 19:04 ` Dragan Simic
2023-10-23 20:47 ` Oswald Buddenhagen
2023-10-23 20:59 ` Dragan Simic
2023-10-23 21:23 ` Jacob Stopak
2023-10-23 21:26 ` Dragan Simic
2023-10-23 21:12 ` Jacob Stopak
2023-10-22 15:50 ` Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 0/6] Noobify format for status, add, restore Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 1/6] status: add noob format from status.noob config Jacob Stopak
2023-10-30 1:32 ` Junio C Hamano
2023-10-30 1:38 ` Dragan Simic
2023-10-30 6:06 ` Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 2/6] status: handle long paths in noob format Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 3/6] add: implement noob mode Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 4/6] add: set unique color for noob mode arrows Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 5/6] restore: implement noob mode Jacob Stopak
2023-10-26 22:46 ` [RFC PATCH v2 6/6] status: add advice status hints as table footer Jacob Stopak
2023-10-27 13:32 ` [RFC PATCH v2 0/6] Noobify format for status, add, restore Dragan Simic
2023-10-27 17:13 ` Jacob Stopak
2023-10-28 0:06 ` Dragan Simic
2023-10-28 2:52 ` Jacob Stopak
2023-10-28 5:55 ` Dragan Simic
2023-10-28 15:21 ` Jacob Stopak
2023-10-28 16:20 ` Dragan Simic
2023-10-28 17:35 ` Jacob Stopak
2023-10-28 17:41 ` Dragan Simic
2023-10-28 18:05 ` Jacob Stopak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231020183947.463882-5-jacob@initialcommit.io \
--to=jacob@initialcommit.io \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).