Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ff071a3
Merge branch 'sa/replay-revert' into tc/replay-ref
gitster Mar 25, 2026
882c8e3
cache-tree: use index state repository in trace2 calls
jayesh0104 Mar 31, 2026
e104e63
Merge branch 'ps/odb-generic-object-name-handling' into ps/odb-cleanup
gitster Apr 1, 2026
55903dc
CodingGuidelines: document our style for flags
pks-t Mar 31, 2026
75c7026
treewide: use enum for `odb_for_each_object()` flags
pks-t Mar 31, 2026
ff2e9d8
odb: rename `odb_write_object()` flags
pks-t Mar 31, 2026
b2d421e
odb: use enum for `odb_write_object` flags
pks-t Mar 31, 2026
c63911b
odb: rename `odb_has_object()` flags
pks-t Mar 31, 2026
109bcb7
odb: drop unneeded headers and forward decls
pks-t Mar 31, 2026
42148da
t7004: replace wc -l with modern test helpers
SiddharthShrimali Apr 1, 2026
c0ce433
read-cache: disable renames in add_files_to_cache
blindmansion Apr 1, 2026
e5ae639
builtin/replay: mark options as not negatable
To1ne Apr 1, 2026
6542cac
replay: use stuck form in documentation and help message
To1ne Apr 1, 2026
23d83f8
replay: allow to specify a ref with option --ref
To1ne Apr 1, 2026
34c17b8
reftable: introduce "reftable-system.h" header
pks-t Apr 2, 2026
b45ea59
reftable/stack: provide fsync(3p) via system header
pks-t Apr 2, 2026
aa89385
reftable/fsck: use REFTABLE_UNUSED instead of UNUSED
pks-t Apr 2, 2026
cb0882d
reftable/system: add abstraction to retrieve time in milliseconds
pks-t Apr 2, 2026
87e4eee
reftable/system: add abstraction to mmap files
pks-t Apr 2, 2026
7d8727f
object-file: avoid ODB transaction when not writing objects
jltobler Apr 7, 2026
a8a773c
Merge branch 'jt/index-fd-wo-repo-regression-fix-maint' into HEAD
gitster Apr 8, 2026
373d43e
t1800: add &&-chains to test helper functions
10ne1 Apr 8, 2026
2e3028a
Merge branch 'ss/t7004-unhide-git-failures'
gitster Apr 8, 2026
9797fed
Merge branch 'ps/odb-cleanup'
gitster Apr 8, 2026
0c0cbd8
Merge branch 'jd/cache-tree-trace-wo-the-repository'
gitster Apr 8, 2026
4fee6ff
Merge branch 'ps/reftable-portability'
gitster Apr 8, 2026
d8c553b
Merge branch 'ng/add-files-to-cache-wo-rename'
gitster Apr 8, 2026
37a4780
Merge branch 'tc/replay-ref'
gitster Apr 8, 2026
fe4ab2e
Merge branch 'jt/index-fd-wo-repo-regression-fix-maint'
gitster Apr 8, 2026
26c27dd
Merge branch 'jt/index-fd-wo-repo-regression-fix'
gitster Apr 8, 2026
2226ffa
run_processes_parallel(): fix order of sigpipe handling
peff Apr 8, 2026
b15384c
A bit more post -rc1
gitster Apr 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Documentation/CodingGuidelines
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,18 @@ For C programs:
unsigned other_field:1;
unsigned field_with_longer_name:1;

- When a function `F` accepts flags, those flags should be defined as `enum
F_flags`. Individual flag definitions should start with `F` and be in
all-uppercase letters. Flag values should be represented via bit shifts.
E.g.

enum frobnicate_flags {
FROBNICATE_FOO = (1 << 0),
FROBNICATE_BAR = (1 << 1),
};

int frobnicate(enum frobnicate_flags flags);

- Array names should be named in the singular form if the individual items are
subject of use. E.g.:

Expand Down
6 changes: 6 additions & 0 deletions Documentation/RelNotes/2.54.0.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,12 @@ Fixes since v2.53
working tree, which was broken.
(merge 339eba65a7 th/backfill-auto-detect-sparseness-fix later to maint).

* add_files_to_cache() used diff_files() to detect only the paths that
are different between the index and the working tree and add them,
which does not need rename detection, which interfered with unnecessary
conflicts.
(merge c0ce43376b ng/add-files-to-cache-wo-rename later to maint).

* Other code cleanup, docfix, build fix, etc.
(merge d79fff4a11 jk/remote-tracking-ref-leakfix later to maint).
(merge 7a747f972d dd/t5403-modernise later to maint).
Expand Down
45 changes: 33 additions & 12 deletions Documentation/git-replay.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ git-replay - EXPERIMENTAL: Replay commits on a new base, works with bare repos t
SYNOPSIS
--------
[verse]
(EXPERIMENTAL!) 'git replay' ([--contained] --onto <newbase> | --advance <branch> | --revert <branch>) [--ref-action[=<mode>]] <revision-range>
(EXPERIMENTAL!) 'git replay' ([--contained] --onto=<newbase> | --advance=<branch> | --revert=<branch>)
[--ref=<ref>] [--ref-action=<mode>] <revision-range>

DESCRIPTION
-----------
Expand All @@ -26,23 +27,23 @@ THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
OPTIONS
-------

--onto <newbase>::
--onto=<newbase>::
Starting point at which to create the new commits. May be any
valid commit, and not just an existing branch name.
+
When `--onto` is specified, the branch(es) in the revision range will be
updated to point at the new commits, similar to the way `git rebase --update-refs`
updates multiple branches in the affected range.

--advance <branch>::
--advance=<branch>::
Starting point at which to create the new commits; must be a
branch name.
+
The history is replayed on top of the <branch> and <branch> is updated to
point at the tip of the resulting history. This is different from `--onto`,
which uses the target only as a starting point without updating it.

--revert <branch>::
--revert=<branch>::
Starting point at which to create the reverted commits; must be a
branch name.
+
Expand All @@ -65,6 +66,16 @@ incompatible with `--contained` (which is a modifier for `--onto` only).
Update all branches that point at commits in
<revision-range>. Requires `--onto`.

--ref=<ref>::
Override which reference is updated with the result of the replay.
The ref must be fully qualified.
When used with `--onto`, the `<revision-range>` should have a
single tip and only the specified reference is updated instead of
inferring refs from the revision range.
When used with `--advance` or `--revert`, the specified reference is
updated instead of the branch given to those options.
This option is incompatible with `--contained`.

--ref-action[=<mode>]::
Control how references are updated. The mode can be:
+
Expand All @@ -79,8 +90,8 @@ The default mode can be configured via the `replay.refAction` configuration vari

<revision-range>::
Range of commits to replay; see "Specifying Ranges" in
linkgit:git-rev-parse[1]. In `--advance <branch>` or
`--revert <branch>` mode, the range should have a single tip,
linkgit:git-rev-parse[1]. In `--advance=<branch>` or
`--revert=<branch>` mode, the range should have a single tip,
so that it's clear to which tip the advanced or reverted
<branch> should point. Any commits in the range whose changes
are already present in the branch the commits are being
Expand Down Expand Up @@ -127,22 +138,22 @@ EXAMPLES
To simply rebase `mybranch` onto `target`:

------------
$ git replay --onto target origin/main..mybranch
$ git replay --onto=target origin/main..mybranch
------------

The refs are updated atomically and no output is produced on success.

To see what would be updated without actually updating:

------------
$ git replay --ref-action=print --onto target origin/main..mybranch
$ git replay --ref-action=print --onto=target origin/main..mybranch
update refs/heads/mybranch ${NEW_mybranch_HASH} ${OLD_mybranch_HASH}
------------

To cherry-pick the commits from mybranch onto target:

------------
$ git replay --advance target origin/main..mybranch
$ git replay --advance=target origin/main..mybranch
------------

Note that the first two examples replay the exact same commits and on
Expand All @@ -154,7 +165,7 @@ What if you have a stack of branches, one depending upon another, and
you'd really like to rebase the whole set?

------------
$ git replay --contained --onto origin/main origin/main..tipbranch
$ git replay --contained --onto=origin/main origin/main..tipbranch
------------

All three branches (`branch1`, `branch2`, and `tipbranch`) are updated
Expand All @@ -165,7 +176,7 @@ commits to replay using the syntax `A..B`; any range expression will
do:

------------
$ git replay --onto origin/main ^base branch1 branch2 branch3
$ git replay --onto=origin/main ^base branch1 branch2 branch3
------------

This will simultaneously rebase `branch1`, `branch2`, and `branch3`,
Expand All @@ -176,7 +187,7 @@ that they have in common, but that does not need to be the case.
To revert commits on a branch:

------------
$ git replay --revert main topic~2..topic
$ git replay --revert=main topic~2..topic
------------

This reverts the last two commits from `topic`, creating revert commits on
Expand All @@ -188,6 +199,16 @@ NOTE: For reverting an entire merge request as a single commit (rather than
commit-by-commit), consider using `git merge-tree --merge-base $TIP HEAD $BASE`
which can avoid unnecessary merge conflicts.

To replay onto a specific commit while updating a different reference:

------------
$ git replay --onto=112233 --ref=refs/heads/mybranch aabbcc..ddeeff
------------

This replays the range `aabbcc..ddeeff` onto commit `112233` and updates
`refs/heads/mybranch` to point at the result. This can be useful when you want
to use bare commit IDs instead of branch names.

GIT
---
Part of the linkgit:git[1] suite
2 changes: 1 addition & 1 deletion builtin/cat-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)

case 'e':
ret = !odb_has_object(the_repository->objects, &oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR);
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR);
goto cleanup;

case 'w':
Expand Down
4 changes: 2 additions & 2 deletions builtin/fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ static int update_local_ref(struct ref *ref,
int fast_forward = 0;

if (!odb_has_object(the_repository->objects, &ref->new_oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))
die(_("object %s not found"), oid_to_hex(&ref->new_oid));

if (oideq(&ref->old_oid, &ref->new_oid)) {
Expand Down Expand Up @@ -1396,7 +1396,7 @@ static int check_exist_and_connected(struct ref *ref_map)
*/
for (r = rm; r; r = r->next) {
if (!odb_has_object(the_repository->objects, &r->old_oid,
HAS_OBJECT_RECHECK_PACKED))
ODB_HAS_OBJECT_RECHECK_PACKED))
return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion builtin/fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ static int mark_object(struct object *obj, enum object_type type,

if (!(obj->flags & HAS_OBJ)) {
if (parent && !odb_has_object(options->repo->objects, &obj->oid,
HAS_OBJECT_RECHECK_PACKED)) {
ODB_HAS_OBJECT_RECHECK_PACKED)) {
printf_ln(_("broken link from %7s %s\n"
" to %7s %s"),
printable_type(options->repo, &parent->oid, parent->type),
Expand Down
2 changes: 1 addition & 1 deletion builtin/index-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
if (startup_info->have_repository) {
read_lock();
collision_test_needed = odb_has_object(the_repository->objects, oid,
HAS_OBJECT_FETCH_PROMISOR);
ODB_HAS_OBJECT_FETCH_PROMISOR);
read_unlock();
}

Expand Down
2 changes: 1 addition & 1 deletion builtin/receive-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)

if (!is_null_oid(new_oid) &&
!odb_has_object(the_repository->objects, new_oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) {
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR)) {
error("unpack should have generated %s, "
"but I can't find it!", oid_to_hex(new_oid));
ret = "bad pack";
Expand Down
2 changes: 1 addition & 1 deletion builtin/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ static int get_push_ref_states(const struct ref *remote_refs,
else if (is_null_oid(&ref->old_oid))
info->status = PUSH_STATUS_CREATE;
else if (odb_has_object(the_repository->objects, &ref->old_oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) &&
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR) &&
ref_newer(&ref->new_oid, &ref->old_oid))
info->status = PUSH_STATUS_FASTFORWARD;
else
Expand Down
38 changes: 24 additions & 14 deletions builtin/replay.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,33 @@ int cmd_replay(int argc,

const char *const replay_usage[] = {
N_("(EXPERIMENTAL!) git replay "
"([--contained] --onto <newbase> | --advance <branch> | --revert <branch>) "
"[--ref-action[=<mode>]] <revision-range>"),
"([--contained] --onto=<newbase> | --advance=<branch> | --revert=<branch>)\n"
"[--ref=<ref>] [--ref-action=<mode>] <revision-range>"),
NULL
};
struct option replay_options[] = {
OPT_STRING(0, "advance", &opts.advance,
N_("branch"),
N_("make replay advance given branch")),
OPT_STRING(0, "onto", &opts.onto,
N_("revision"),
N_("replay onto given commit")),
OPT_BOOL(0, "contained", &opts.contained,
N_("update all branches that point at commits in <revision-range>")),
OPT_STRING(0, "revert", &opts.revert,
N_("branch"),
N_("revert commits onto given branch")),
OPT_STRING(0, "ref-action", &ref_action,
N_("mode"),
N_("control ref update behavior (update|print)")),
OPT_STRING_F(0, "onto", &opts.onto,
N_("revision"),
N_("replay onto given commit"),
PARSE_OPT_NONEG),
OPT_STRING_F(0, "advance", &opts.advance,
N_("branch"),
N_("make replay advance given branch"),
PARSE_OPT_NONEG),
OPT_STRING_F(0, "revert", &opts.revert,
N_("branch"),
N_("revert commits onto given branch"),
PARSE_OPT_NONEG),
OPT_STRING_F(0, "ref", &opts.ref,
N_("branch"),
N_("reference to update with result"),
PARSE_OPT_NONEG),
OPT_STRING_F(0, "ref-action", &ref_action,
N_("mode"),
N_("control ref update behavior (update|print)"),
PARSE_OPT_NONEG),
OPT_END()
};

Expand All @@ -122,6 +130,8 @@ int cmd_replay(int argc,
opts.contained, "--contained");
die_for_incompatible_opt2(!!opts.revert, "--revert",
opts.contained, "--contained");
die_for_incompatible_opt2(!!opts.ref, "--ref",
!!opts.contained, "--contained");

/* Parse ref action mode from command line or config */
ref_mode = get_ref_action_mode(repo, ref_action);
Expand Down
2 changes: 1 addition & 1 deletion builtin/show-ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static void show_one(const struct show_one_options *opts,
struct object_id peeled;

if (!odb_has_object(the_repository->objects, ref->oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))
die("git show-ref: bad ref %s (%s)", ref->name,
oid_to_hex(ref->oid));

Expand Down
2 changes: 1 addition & 1 deletion builtin/unpack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
if (!delta_data)
return;
if (odb_has_object(the_repository->objects, &base_oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))
; /* Ok we have this one */
else if (resolve_against_held(nr, &base_oid,
delta_data, delta_size))
Expand Down
14 changes: 7 additions & 7 deletions cache-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ int cache_tree_fully_valid(struct cache_tree *it)
return 0;
if (it->entry_count < 0 ||
odb_has_object(the_repository->objects, &it->oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))
return 0;
for (i = 0; i < it->subtree_nr; i++) {
if (!cache_tree_fully_valid(it->down[i]->cache_tree))
Expand Down Expand Up @@ -292,7 +292,7 @@ static int update_one(struct cache_tree *it,

if (0 <= it->entry_count &&
odb_has_object(the_repository->objects, &it->oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))
return it->entry_count;

/*
Expand Down Expand Up @@ -400,7 +400,7 @@ static int update_one(struct cache_tree *it,
if (is_null_oid(oid) ||
(!ce_missing_ok &&
!odb_has_object(the_repository->objects, oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))) {
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))) {
strbuf_release(&buffer);
if (expected_missing)
return -1;
Expand Down Expand Up @@ -448,15 +448,15 @@ static int update_one(struct cache_tree *it,
struct object_id oid;
hash_object_file(the_hash_algo, buffer.buf, buffer.len,
OBJ_TREE, &oid);
if (odb_has_object(the_repository->objects, &oid, HAS_OBJECT_RECHECK_PACKED))
if (odb_has_object(the_repository->objects, &oid, ODB_HAS_OBJECT_RECHECK_PACKED))
oidcpy(&it->oid, &oid);
else
to_invalidate = 1;
} else if (dryrun) {
hash_object_file(the_hash_algo, buffer.buf, buffer.len,
OBJ_TREE, &it->oid);
} else if (odb_write_object_ext(the_repository->objects, buffer.buf, buffer.len, OBJ_TREE,
&it->oid, NULL, flags & WRITE_TREE_SILENT ? WRITE_OBJECT_SILENT : 0)) {
&it->oid, NULL, flags & WRITE_TREE_SILENT ? ODB_WRITE_OBJECT_SILENT : 0)) {
strbuf_release(&buffer);
return -1;
}
Expand Down Expand Up @@ -488,12 +488,12 @@ int cache_tree_update(struct index_state *istate, int flags)
prefetch_cache_entries(istate, must_check_existence);

trace_performance_enter();
trace2_region_enter("cache_tree", "update", the_repository);
trace2_region_enter("cache_tree", "update", istate->repo);
transaction = odb_transaction_begin(the_repository->objects);
i = update_one(istate->cache_tree, istate->cache, istate->cache_nr,
"", 0, &skip, flags);
odb_transaction_commit(transaction);
trace2_region_leave("cache_tree", "update", the_repository);
trace2_region_leave("cache_tree", "update", istate->repo);
trace_performance_leave("cache_tree_update");
if (i < 0)
return i;
Expand Down
4 changes: 2 additions & 2 deletions fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
if (commit) {
if (mark_tags_complete_and_check_obj_db) {
if (!odb_has_object(the_repository->objects, oid,
HAS_OBJECT_RECHECK_PACKED))
ODB_HAS_OBJECT_RECHECK_PACKED))
die_in_commit_graph_only(oid);
}
return commit;
Expand Down Expand Up @@ -2016,7 +2016,7 @@ static void update_shallow(struct fetch_pack_args *args,
struct object_id *oid = si->shallow->oid;
for (i = 0; i < si->shallow->nr; i++)
if (odb_has_object(the_repository->objects, &oid[i],
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
ODB_HAS_OBJECT_RECHECK_PACKED | ODB_HAS_OBJECT_FETCH_PROMISOR))
oid_array_append(&extra, &oid[i]);
if (extra.nr) {
setup_alternate_shallow(&shallow_lock,
Expand Down
Loading