Изменение коммита с эффектами hg cp --after

У меня есть файл before.txt, который я хочу разделить на два файла меньшего размера. То, что я сделал должен, было

$ hg cp before.txt part1.txt # Then edit part1.txt
$ hg mv before.txt part2.txt # Then edit part2.txt
$ hg commit

Тогда как part1.txt, так и part2.txt будут иметь before.txt как часть своей истории, поэтому разница будет отображаться как удаление частей большего файла, а не удаление одного файла и создание нового с частью его содержимого.

Однако то, что я на самом деле сделал, было

$ cp before.txt part1.txt # Then edit part1.txt
$ hg mv before.txt part2.txt # Then edit part2.txt
$ hg commit

Так что файл before.txt присутствует только в истории одного из двух моих файлов. Если бы я не побежал hg commit, мне кажется очевидным, что я мог бы решить свою проблему с помощью

$ hg cp --after before.txt part1.txt

или что-то похожее на это. И я не продвигал этот коммит вверх по течению, поэтому я должен могу редактировать его, как мне нравится. Но я не могу понять, как это сделать. Когда я запускаю этот hg cp, я вижу:

$ hg cp --after before.txt part1.txt
before.txt: No such file or directory
before.txt: No such file or directory
abort: no files to copy

Это имеет смысл: он не может записать это редактирование как часть нового коммита, потому что исходный файл не существует. Я хочу, чтобы записать его как часть предыдущего коммита, но я не знаю, как это сделать, кроме как записать его как часть нового коммита, а затем amendвставить в предыдущий коммит.


4
731
2

Ответы:

Решено

Вот один из способов исправить эту ситуацию:

$ hg shelve       # get any miscellaneous, unrelated changes out of the way
$ hg up <parent of revision with the mistake in it>

$ hg cp before.txt part1.txt 
$ hg mv before.txt part2.txt 

$ hg revert -r <revision with the mistake in it> --all
$ hg commit
$ hg strip <revision with the mistake in it>

(I didn't actually try all these commands, hopefully no typos!)

Первый шаг является необязательным в зависимости от состояния ваших рабочих каталогов.

Теперь part1.txt и part2.txt должны иметь правильное содержимое. Использование revert было просто для того, чтобы избавить от необходимости вручную повторно редактировать изменения файла. Но вы также можете просто повторить это вручную, если это кажется проще.

Использование revert для извлечения в рабочую папку эффекты другого набора изменений — трюк, который я часто использую. Это похоже на ручной способ внесения поправок, который дает вам полную гибкость. Но это хорошо работает только в том случае, если ревизия, которую вы возвращаете в свою рабочую копию к, тесно связана с ревизией, которая является родителем рабочей копии. В противном случае это создаст многочисленные неприятные изменения.


на основе ответа @DaveInCaz, вот MCVE

mkdir tmpdir
cd tmpdir
hg init

echo line1 > before.txt
echo line2 >> before.txt
hg add before.txt
hg commit -m "my before"

cp before.txt part1.txt
hg add part1.txt
hg mv before.txt part2.txt
echo line1 > part1.txt
echo line2 > part2.txt
hg commit -m "my bad"


hg shelve
hg up -r -2

hg cp before.txt part1.txt
hg cp before.txt part2.txt
hg revert -r -1 --all
hg commit -m "my good"

hg strip -r -2

некоторые замечания:

  • дважды hg cp, потому что позже revert удалит файл before.txt для нас, иначе он будет жаловаться на его отсутствие
  • revert --all по крайней мере в моей версии требуется указать, что ревертируется
  • hg shelve должен быть в безопасности, прежде чем переключаться на другую версию
  • hg up -r -2 мог бы -C с тех пор, как предыдущий shelve сделал нас в безопасности, таким образом, вы можете повторить последние шаги с разными подходами и посмотреть, что вам больше подходит.