'Git commit --amend` затрагивает больше файлов, чем необходимо? - PullRequest
0 голосов
/ 08 февраля 2019

У меня часто возникает следующее:

  1. Изменение файлов A, B и C.
  2. Передача изменений с помощью git commit.
  3. Сборка проекта, поэтому сборка обновлена.
  4. Внесите исправление / исправление только в файл A.
  5. Выполните git commit -a --amend (или git commit --amend path/to/A)
  6. Построение проекта постепенно.

Теперь, поскольку я изменил только файл A с момента последнего создания, я ожидал бы, что будет восстановлен только файл A, но то, что я всегда вижузаключается в том, что все A, B и C (т. е. все файлы, затронутые всей фиксацией) перестраиваются.

Мне кажется, что git commit --amend it touch вставляет / удаляет последние измененные метки временикаждого из A, B и C, хотя я только добавляю модификацию A к коммиту.

Это необходимо?Можно ли этого избежать, поэтому касаются только A и перестраивают только A?

Если это имеет значение, мой проект находится на C ++, а моя система сборки - cmake + ninja, но я думаю, что это во многом помимоОтметим, что для систем сборки достаточно стандартно полагаться на последние измененные временные метки, чтобы определить, что нужно перестраивать.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

git commit не касается любых файлов в вашем рабочем дереве.Не имеет значения, используете ли вы здесь --amend.

A git commit без -a не не использует любые файлы из вашего рабочего дерева, но git commit -a имеет Gitпо сути, сначала запустите git add -u, что прочитает некоторые файлы из рабочего дерева, чтобы скопировать их в индекс.Затем, в любом случае - с или без -a - git commit строит новый коммит из того, что находится в индексе.

Новый коммит, после его создания, имеет какой-то новый, уникальный, никогда ранее не виданныйидентификатор хешаЕсли вы делаете обычный git commit (без --amend), в вашем хранилище есть несколько коммитов, каждый со своим уникальным хеш-идентификатором, а last такой коммит имеет некоторый хеш-идентификаторH:

... <-F <-G <-H   <-- your-branch (HEAD)

(Здесь заглавные буквы обозначают фактические необработанные хэш-идентификаторы, которые выглядят случайными, но на самом деле это не так, но не являются предсказуемыми.) Новый коммит получаетего новый уникальный хэш-идентификатор I, а внутри I сохраненный родительский хэш-идентификатор H.Git записывает новый идентификатор в имя ветви, давая:

...--F--G--H--I   <-- your-branch (HEAD)

При --amend разница в том, что вместо нового коммита I он указывает на существующий коммит H, Git создаетновый коммит с таким же родителем, который есть у H, в данном случае G.Эффект заключается в том, что H отталкивается в сторону:

          H
         /
...--F--G--I   <-- your-branch (HEAD)

Существующий коммит H не изменяется, но кажется исчезающим: его нельзя найти, начиная с I и работая в обратном направлении.,Так что git log скрывает это, и кажется, что оно пропало, как будто Git каким-то образом изменил H.Git не имеет;H все еще не поврежден.По умолчанию его также можно восстановить в течение как минимум 30 дней, поскольку идентификатор хеша хранится в том, что Git называет reflogs .Но он выглядит пропавшим.

Если вы видите, что различные файлы перестраиваются, это не потому, что сам Git коснулся исходных файлов.Что-то еще, возможно, коснулось исходных файлов, или - мое предположение, но только предположение - ваша система сборки может пометить их как зависящие от конкретного хэша Git commit: так как I имеет хеш, отличный от H, и сборкаАртефакты были следствием H, а не I, теперь они устарели.

(Другие возможности включают, конечно, перехватчики Git, которые изменяют временные метки на файлах.)

0 голосов
/ 08 февраля 2019

Один из способов избежать этого (вручную) - выполнить все коммиты без внесения изменений и, когда вы закончите с изменениями, интерактивно перебазировать сдавить коммиты (те, которые вы вносите сейчас)

...