В общем, это явно невозможно, но достаточно легко достать достаточно дел, чтобы сделать его стоящим. Следующее - в основном чистая теория: для Git нет ничего, чтобы сделать это.
Подумайте, как делать снимки, которые могут быть преобразованы в дельта (потому что они есть). Ваша задача, учитывая последовательность фиксаций:
...--A--B--C--D--...
(мы несколько произвольно ограничивать это линейные Фиксации-модов к алгебре для ведения слияний очевидны, хотя и грязный) мы будем вычислять Д B, ΔC и ΔD. ΔB является просто B-A, ΔC является C-B и т. Д. Конечно, результатом «вычитания» является набор diff (или набор изменений), а не простое число. Эти дельта, однако, являются тем, что вы видите при запуске git show
(или git diff
). (Вы также можете избежать обнаружения переименования здесь, если попытаетесь сделать это по-настоящему и сделать его надежным.)
Далее мы хотим увидеть, включает ли ΔC "-ΔB или включает ли ΔD" "-ΔB. A нормальный git revert
- отрицательная дельта, поэтому мы ищем набор изменений, который не является самовосстанавливающимся, но все же содержит a revert.
Когда мы смотрим на сырье формы git diff
производства, мы находим, что для строго измененных файлов, то разница просто много шаблонных-у @@
и ломоть-контекстных линия вокруг изменения, которые выражаются исключительно как -
и +
строки: удалить старый, вставить новый.
Reversion состоит из создания . изменение в обратном направлении: добавьте удаленные строки, удаляя добавленные строки с тем же контекстом в том же порядке.
Изменение, которое содержит реверсию, по крайней мере, для легко обнаружить случаи, просто изменение, которое включает в себя реверсии, то есть, добавляет обратно удалены строк при удалении добавленных линий, с тем же контекстом, в тот же порядок, в то же время делая некоторые другие отдельные изменения.
Другими словами, если ΔC = -ΔB + ∂C, или ΔD = -ΔB + ∂D, то мы предположим, что одна из этих дельт была «неправильной»: она должна была быть только ∂C или просто ∂D.
Программа git patch-id
может вычислять идентификатор патча для любой diff-hunk, поэтому, чтобы определить, является ли какой-то большой треугольник ΔX отрицательным от некоторого предыдущего ΔB плюс несколько меньших ∂X, вы можете просто разделить оригинал ΔB в его составные куски, отрицать каждый из них и получать его идентификатор патча. [Изменить: используйте André Sassi's suggestion - упростите это, предварительно вычислив обратный дифференциал, либо используя BB^как два входа для git diff
, либо используя флаг -R
, который доступен как в , так и git show
.] Поместите их в основной список L Затем для любого последующего фиксации X, начиная с l = L, пройдите через компонентные куски ΔX. Вычислите идентификатор патча hunk и посмотрите, соответствует ли это следующему значению, указанному в вашем списке. Если да, отбросьте один предмет от l. Если вы опустили последний вещь от l, вы только что обнаружили, что ΔX включает -ΔB. В противном случае перейдите к следующему столбцу в ΔX. Если вы достигнете конца ΔX, не отбрасывая все значения от l, вы пришли к выводу, что ΔX не включает -ΔB.
Повторите все подозрительные коммиты, и вы увидите, сможете ли вы автоматически найти эти «случайные обратные». Обратите внимание, что преднамеренная реверсия не будет иметь ничего , но -ΔB, а также будет иметь сообщение фиксации, в котором говорится «вернуться ...».
Похоже, что существует ошибка, связанная с тем, как настроены редакторы вашей команды. Я никогда не сталкивался с этой проблемой. – Kenyon
Уверен, что это проблема редактора, которая в конечном итоге должна быть решена с помощью некоторой лучшей конфигурации. Однако, столкнувшись с ним несколько раз с разными, я хочу, чтобы его можно было обнаружить. – tillmo
У меня нет правильного ответа (пока), но я бы сказал, что итерация по всем коммитам и вычисление пересечения их обратного diff ('commit..commit ^') с diff от его родителя ('commit^^ .. commit ^) мог найти по крайней мере большинство из этих случаев. –