From: Johannes Schindelin <johannes.schindelin@xxxxxx> It is quite possible that the loose object cache gets stale when new objects are written. Or that a new pack was installed. In those cases, get_oid() would potentially say that it cannot find a given object, even if it should find it. Let's blow away the loose object cache as well as the read packs and try again in that case. Note: this does *not* affect the code path that was introduced to help avoid looking for the same non-existing objects (which made some operations really expensive via NFS): that code path is handled by the `OBJECT_INFO_QUICK` flag (which does not even apply to `get_oid()`, which has no equivalent flag, at least at the time this patch was written). This incidentally fixes the problem identified earlier where an interactive rebase wanted to re-read (and validate) the todo list after an `exec` command modified it. Helped-by: Jeff King <peff@xxxxxxxx> Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- sha1-name.c | 13 ++++++++++++- t/t3429-rebase-edit-todo.sh | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sha1-name.c b/sha1-name.c index 6dda2c16df..36a6602696 100644 --- a/sha1-name.c +++ b/sha1-name.c @@ -415,7 +415,7 @@ static enum get_oid_result get_short_oid(const char *name, int len, struct object_id *oid, unsigned flags) { - int status; + int status, attempts = 0; struct disambiguate_state ds; int quietly = !!(flags & GET_OID_QUIETLY); @@ -438,10 +438,21 @@ static enum get_oid_result get_short_oid(const char *name, int len, else ds.fn = default_disambiguate_hint; +try_again: find_short_object_filename(&ds); find_short_packed_object(&ds); status = finish_object_disambiguation(&ds, oid); + /* + * If we did not find it, do the usual reprepare() slow-path, since the + * object may have recently been added to the repository or migrated + * from loose to packed. + */ + if (status == MISSING_OBJECT && !attempts++) { + reprepare_packed_git(the_repository); + goto try_again; + } + if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) { struct oid_array collect = OID_ARRAY_INIT; diff --git a/t/t3429-rebase-edit-todo.sh b/t/t3429-rebase-edit-todo.sh index 83e5bb5eba..d5d2925a44 100755 --- a/t/t3429-rebase-edit-todo.sh +++ b/t/t3429-rebase-edit-todo.sh @@ -11,7 +11,7 @@ test_expect_success 'rebase exec modifies rebase-todo' ' test -e F ' -test_expect_failure SHA1 'loose object cache vs re-reading todo list' ' +test_expect_success SHA1 'loose object cache vs re-reading todo list' ' GIT_REBASE_TODO=.git/rebase-merge/git-rebase-todo && export GIT_REBASE_TODO && write_script append-todo.sh <<-\EOS && -- gitgitgadget