Re: git mv after the fact
- From
Junio C Hamano <gitster@pobox.com>
- Date
- May 28, 2026, 20:36 UTC
- Message-ID
- <xmqq5x47jmpm.fsf@gitster.g>
- In-Reply-To
- <1FEDBC47-5DDB-4C42-A7C7-695630D330BF@gmail.com>
Ben Knoble <ben.knoble@gmail.com> writes:
Show 27 quoted lines
>> Le 27 mai 2026 à 19:24, Junio C Hamano <gitster@pobox.com> a écrit : >> >> Chris Torek <chris.torek@gmail.com> writes: >> >>>> Chris Torek <chris.torek@gmail.com> writes: >>>>> A flag for "git mv" would be convenient (and slightly moreefficient ... >>>> >>> >>> On Tue, May 26, 2026 at 8:09 PM Junio C Hamano <gitster@pobox.com> wrote: >>>> May be convenient, but I do not get the "efficient" part. >>> >>> A normal `git mv` renames the index entry and the file in the working >>> tree without running `git add` on the *contents*, so there's no new hash >>> computation. Presumably a `git mv --after foo bar` would do the same: verify >>> that there is no existing `bar` in the index, that there is an existing `foo` in >>> the index, and that there is no `foo` but there is a `bar` in the working tree, >>> and then it would rename (add-and-remove, really, because of sorting) >>> the index entry, without scanning the working tree contents. >>> >>> In other words, we skip reading the 3 terabyte file, or whatever. >> >> Yup, that matches what I wrote. We do not rehash and we only write >> the index just once. > > One thing I wondered: if we don’t have an exact move but assume (by not hashing), doesn’t that mean the index would differ from what’s on disk? I originally thought that might be a problem, but the more I thought the more I realized that’s a fairly typical state anyway. > > Just seemed like a potential footgun to me, but perhaps not worth worrying about.
Good point. Actually with or without --after/--cached, we do not have to rehash, and more importantly, we should not rehash.
As you can do this already
$ date >old.txt
$ git add old.txt
$ date >>old.txt
... now old.txt is _dirty_
$ git mv old.txt new.txtI do not think it is unusual to have the contents you have in your working tree files diverge from the contents you last 'git add'ed to the index. You do *not* want to rehash. The index entry for new.txt must be left not-up-to-date, which is achieved in the above sequence by retaining the file timestamp of old.txt at the "git add" time even after "git mv" (i.e. new.txt has the timestamp and size of the old.txt after it got the second "date" output, the index entry records one generation old one, and would not match). If we do the "index-entry only" move, i.e.
$ date >old.txt
$ git add old.txt
$ date >>old.txt
... now old.txt is _dirty_
$ mv old.txt new.txt
... oops, we forgot to tell git
$ git mv --cached old.txt new.txtwe need to make sure that we leave the cache entry dirty for new.txt in the index.