atesting.ru Аптечка сисадмина,Ошибка Git: исправление ошибок и наведение порядка в коммитах

Git: исправление ошибок и наведение порядка в коммитах

Введение¶

Git (произн. «гит») — распределённая система управления версиями файлов. Проект был создан Линусом Торвальдсом для управления разработкой ядра Linux. На сегодняшний день поддерживается Джунио Хамано.

Система спроектирована как набор программ, специально разработанных с учётом их использования в скриптах. Это позволяет удобно создавать специализированные системы контроля версий на базе Git или пользовательские интерфейсы. Например, Cogito является именно таким примером фронтенда к репозиториям Git, а StGit использует Git для управления коллекцией патчей.

Git поддерживает быстрое разделение и слияние версий, включает инструменты для визуализации и навигации по нелинейной истории разработки. Как и Darcs, BitKeeper, Mercurial, SVK, Bazaar и Monotone, Git предоставляет каждому разработчику локальную копию всей истории разработки; изменения копируются из одного репозитория в другой.

Удалённый доступ к репозиториям Git обеспечивается git-daemon, gitosis, SSH- или HTTP-сервером. TCP-сервис git-daemon входит в дистрибутив Git и является наряду с SSH наиболее распространённым и надёжным методом доступа. Метод доступа по HTTP, несмотря на ряд ограничений, очень популярен в контролируемых сетях, потому что позволяет использовать существующие конфигурации сетевых фильтров.

直前のコミットを変更する: git commit —amend

コマンドは、直前のコミットを変更する最も便利な方法です。これを使用することでまったく新しいコミットを作成する代わりに、ステージングされた変更を前のコミットと組み合わせることができます。また、スナップショットを変更せずに、前のコミット メッセージを単純に変更する際にも使用されます。しかし、改変では、直前のコミットが変更されるだけでなく、全体が置き換えられます。つまり、修正されたコミットは独自の ref を持つ新しいエンティティとなります。Git にとってはまったく新しいコミットのように見えます (以下の図ではアスタリスク (*) を使用して視覚化されています)。 の使用には、いくつかの一般的なシナリオがあります。次のセクションでは、使用例を紹介します。

直前の Git コミット メッセージを変更する

コミットを行ったばかりで、コミット ログ メッセージに間違いがあるとします。ステージ領域に何もない状態でこのコマンドを実行すると、スナップショットを書き換えることなく直前のコミット メッセージの編集を行うことができます。

開発現場では不完全なコミットが実行されることが日常的に起こります。ファイルのステージを忘れたり、コミット メッセージのフォーマッティングを間違えたりすることはよくあるのです。 フラグは、このような軽度の誤操作を修正する場合に便利です。

オプションを追加すると、エディターを開くプロンプトを表示せずに、コマンド ラインから新しいメッセージに渡すことができます。

コミット済みのファイルを変更する

次の例では、Git ベースの開発における一般的なシナリオを示します。いくつかのファイルを編集して一つのスナップショットとしてコミットする予定であったが、最初にコミットしたときに片方のファイルを追加し忘れたとします。この修正を行うには、単にそのファイルをステージングし、 フラグを指定してコミットします。

フラグを使用すると、コミット メッセージを変更せずに、コミットに変更を加えることができます。結果のコミットは不完全なコミットに置き換えられ、 と への変更が 1 つのスナップショットでコミットされたようになります。

公開済みコミットの修正は厳禁

修正されたコミットは実際にはまったく新しいコミットであり、以前のコミットは現在のブランチから削除されます。これにより、公開済みのスナップショットを取り消す場合と同様の問題が生じます。他の開発者が既に作業のベースとして使用しているコミットを修正しないようにしてください。これは開発者に混乱をもたらし、回復は面倒です。

要約

レビューを行うには、 を使用すると、直前のコミットへ移動して、そこに新しいステージングされた変更を追加します。 コミットを使用して、適用対象の Git ステージング領域から変更を追加または削除できます。変更がステージングされていない場合でも、 を使用すると、直前のコミット メッセージ ログを変更するよう求めるメッセージが表示されます。他のチーム メンバーと共有しているコミットで を使用する際には注意が必要です。他のユーザーと共有しているコミットを変更すると、複雑で時間のかかる競合解決が必要となる可能性があります。

Ранние годы

В ранние годы использования git я никогда особо не заморачивался о том, как писать комментарии к коммитам. Большая часть моих комментариев к коммитам выглядела следующим образом:

У меня не возникало даже мысли использовать тело коммита. Моей дежурной командой неизменно служила . Когда вы работаете в компании, которая занимается пиаром, код ревью не является для вас привычной практикой

Никто даже не думал предложить мне обратить внимание на мои комментарии к коммитам. Ситуация изменилась, когда я перешел в компанию с хорошей инженерной культурой, где я научился написанию комментариев, четко объясняющих, что это за коммит, как неотъемлемой части моей работы

  1. Отделяйте заголовок от тела пустой строкой

  2. Ограничивайте заголовок 50 символами

  3. Пишите заголовок с заглавной буквы

  4. Не ставьте точку в конце заголовка

  5. Используйте повелительное наклонение в заголовке

  6. Переходите на следующую строку в теле на 72 символах

  7. В теле отвечайте на вопросы что и почему, а не как

Перенесемся на два месяца назад — я, насмотревшись комментариев к коммитам других разработчиков, чтобы использовать их в качестве примеров для структурирования моих собственных комментариев, продолжаю пытаться применять правила, указанные выше. Одна вещь, которая мешает мне написать хороший комментарий к коммиту, — это неспособность определить, какие изменения относятся к какому комментарию. Каждый раз, когда я хочу закоммитить свои изменения, у меня запускается мысленный процесс, пытающийся разделить изменения, чтобы их можно было сгруппировать как можно более «атомарно».

Производительность

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

Некоторые системы управления версиями руководствуются именами файлов при работе с деревом файлов и ведении истории версий. Вместо обработки названий система Git анализирует содержимое

Это важно, поскольку файлы исходного кода часто переименовывают, разделяют и меняют местами. Объектные файлы репозитория Git формируются с помощью дельта‑кодирования (фиксации отличий содержимого) и компрессии

Кроме того, такие файлы в чистом виде хранят объекты с содержимым каталога и метаданными версий.

Вместе с тем распределенная архитектура системы сама по себе обеспечивает существенный прирост производительности.

Рассмотрим пример: разработчик Элис меняет исходный код. Она добавляет функцию для будущей версии 2.0, после чего делает коммит и сопровождает изменения описанием. Затем она разрабатывает другую функцию и делает еще один коммит. Разумеется, эти изменения сохраняются в истории в виде отдельных рабочих элементов. Затем Элис переключается на ветку, соответствующую версии 1.3 того же ПО — так она сможет исправить баг, затрагивающий эту конкретную версию. Это нужно, чтобы команда Элис могла выпустить версию 1.3.1 с исправлениями до завершения работы над версией 2.0. Затем Элис вернется к ветке для версии 2.0 и продолжит работу над соответствующими функциями. Все перечисленные действия можно выполнить без доступа к сети, поэтому система Git отличается быстротой и надежностью, даже если работать в самолете. Когда Элис будет готова отправить все внесенные изменения в удаленный репозиторий, ей останется лишь выполнить команду push.

Letzten Commit ändern: git commit —amend

Der Befehl ist eine praktische Möglichkeit zum Ändern des aktuellsten Commits. So kannst du Änderungen auf Staging-Ebene mit dem vorherigen Commit kombinieren, statt einen ganz neuen Commit zu erstellen. Mit diesem Befehl kannst du auch einfach die vorherige Commit-Nachricht bearbeiten, ohne den entsprechenden Snapshot zu ändern. Durch das Korrigieren wird jedoch der aktuellste Commit nicht nur geändert, sondern komplett ersetzt. Das bedeutet, dass der korrigierte Commit eine neue Einheit mit eigener Referenz darstellt. Git behandelt ihn wie einen völlig neuen Commit, was an dem Sternsymbol (*) im unten stehenden Diagramm zu erkennen ist. Es gibt einige häufige Szenarien zur Verwendung von . In den folgenden Abschnitten stellen wir einige Beispiele vor.

Die aktuellste Commit-Nachricht in Git ändern

Nehmen wir mal an, du hast gerade einen Commit durchgeführt und dir ist in der Protokollnachricht des Commits ein Fehler unterlaufen. Führst du diesen Befehl aus, wenn noch nichts in die Staging-Ebene verschoben wurde, dann kannst du die Nachricht des vorherigen Commits bearbeiten, ohne den entsprechenden Snapshot zu verändern.

Im Laufe der tagtäglichen Entwicklung werden immer wieder verfrühte Commits durchgeführt. Man vergisst gern einmal, eine Datei auf die Staging-Ebene zu verschieben, oder macht einen Fehler bei der Formatierung einer Commit-Nachricht. Mit der Kennzeichnung lassen sich solche kleineren Fehler leicht beheben.

Durch Hinzufügen der Option kannst du eine neue Nachricht über die Befehlszeile eingeben, ohne einen Editor öffnen zu müssen.

Bestätigte Dateien ändern

Das folgende Beispiel stellt ein häufig vorkommendes Szenario bei einer Git-basierten Entwicklung dar. Nehmen wir mal an, wir haben einige Dateien bearbeitet, für die wir einen Commit mit einem einzigen Snapshot durchführen wollen. Doch dann vergessen wir im ersten Anlauf, eine dieser Dateien hinzuzufügen. Um den Fehler zu beheben, müssen wir einfach die andere Datei in die Staging-Ebene verschieben und den Commit mit der Kennzeichnung durchführen:

Mit der Kennzeichnung kannst du Korrekturen an deinem Commit vornehmen, ohne die entsprechende Commit-Nachricht zu ändern. Der daraus entstehende Commit ersetzt den unvollständigen Commit. Es sieht dann so aus, als hätten wir für die Änderungen an und einen Commit mit einem einzigen Snapshot durchgeführt.

Öffentliche Commits nicht korrigieren

Korrigierte Commits sind tatsächlich komplett neue Commits. Daher befindet sich der vorherige Commit nicht mehr in deinem aktuellen Branch. Das hat dieselben Folgen wie das Zurücksetzen eines öffentlichen Snapshots. Vermeide es daher, einen Commit zu korrigieren, auf den andere Entwickler ihre Arbeit aufbauen. Für Entwickler ist das eine verwirrende Situation und die Lösung ist kompliziert.

Zusammenfassung

Mit dem Befehl kannst du zum Reviewen den aktuellsten Commit abrufen und neue Änderungen aus der Staging-Ebene hinzufügen. Du kannst Änderungen aus der Staging-Umgebung von Git entfernen oder ihr hinzufügen, um einen Commit mit dem Befehl darauf anzuwenden. Wurden noch keine Änderungen auf die Staging-Ebene verschoben, wirst du durch weiterhin dazu aufgefordert, die letzte Commit-Protokollnachricht zu ändern. Sei daher vorsichtig, wenn du auf Commits anwendest, die mit anderen Teammitgliedern geteilt werden. Einen Commit zu ändern, der mit einem anderen Benutzer geteilt wird, kann zu Merging-Konflikten führen und verwirrende und langwierige Lösungen erfordern.

Ранние годы

В ранние годы использования git я никогда особо не заморачивался о том, как писать комментарии к коммитам. Большая часть моих комментариев к коммитам выглядела следующим образом:

У меня не возникало даже мысли использовать тело коммита. Моей дежурной командой неизменно служила . Когда вы работаете в компании, которая занимается пиаром, код ревью не является для вас привычной практикой

Никто даже не думал предложить мне обратить внимание на мои комментарии к коммитам. Ситуация изменилась, когда я перешел в компанию с хорошей инженерной культурой, где я научился написанию комментариев, четко объясняющих, что это за коммит, как неотъемлемой части моей работы

  1. Отделяйте заголовок от тела пустой строкой

  2. Ограничивайте заголовок 50 символами

  3. Пишите заголовок с заглавной буквы

  4. Не ставьте точку в конце заголовка

  5. Используйте повелительное наклонение в заголовке

  6. Переходите на следующую строку в теле на 72 символах

  7. В теле отвечайте на вопросы что и почему, а не как

Перенесемся на два месяца назад — я, насмотревшись комментариев к коммитам других разработчиков, чтобы использовать их в качестве примеров для структурирования моих собственных комментариев, продолжаю пытаться применять правила, указанные выше. Одна вещь, которая мешает мне написать хороший комментарий к коммиту, — это неспособность определить, какие изменения относятся к какому комментарию. Каждый раз, когда я хочу закоммитить свои изменения, у меня запускается мысленный процесс, пытающийся разделить изменения, чтобы их можно было сгруппировать как можно более «атомарно».

Команда git add

Команда commit отправляет файлы в локальный репозиторий.

Однако перед выполнением команды commit надо подготовить файлы – составить список тех из них, которые будут отправлены в репозиторий. Команда git add позволяет это сделать – добавляет файлы и папки в индекс (область staging area). В GIT есть понятие staged files – это файлы, которые попадут в следующий снимок при выполнении команды commit.

Дело в том, что в параметрах commit не указывается, какие файлы включать в снимок. Это делается заранее в команде add, а в команде commit пишется просто комментарий и в репозиторий отправляются все подготовленные файлы из индекса (staging area).

Можно добавлять в индекс как файлы, так и папки. Например, эта команда подготовит для будущего снимка папку <имя_папки1> и файл <имя_файла1>:

git add <имя_файла1> <имя_папки1>

При этом все остальные файлы, даже если они отслеживаются в репозитории (tracked files) и были отредактированы (edited files), в следующий снимок не попадут.

Есть удобные вариации команды add:

git add -A добавляет все файлы (вновь созданные, измененные и удаленные)
git add . добавляет вновь созданные и измененные файлы, но не удаленные
git add -u добавляет измененные и удаленные, но не вновь созданные

Нетрудно заметить, что команда:

git add -A

эквивалентна двум поочередно выполненным командам:

git add .
git add -u

Удаление файлов из репозитория и с диска

Возможно, вам покажется странной фраза “добавляет удаленные файлы”. На самом деле это нормально: чтобы удалить файл из локального репозитория, недостаточно просто удалить его с диска. Надо после этого еще выполнить определенную команду git.

Если речь идет об отдельном файле, то команда:

git rm <имя_файла>

добавляет файл <имя_файла> в индекс как удаленный. При этом файл удаляется и с диска, если еще не был удален оттуда.

А команда:

git add -u

позволяет выполнить git rm для всех удаленных с диска файлов одновременно, то есть отправить их в индекс.

Удаление файлов только из репозитория

Бывает надо удалить файлы из репозитория, но не удалять с диска. Например, мы отправили в репозиторий логи, которым там не место.

А на диске они должны оставаться. Чтобы добавить этот лог в индекс как удаленный, но оставить его при этом на диске, выполним команду:

git rm --cached mylogfile.log

То же самое для папки делается так:

git rm --cached -r mydirectory

Порядок действий

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

Это меняет базовую модель разработки для пользователей Git. Вместо того чтобы вносить изменения и выполнять коммиты непосредственно в центральный репозиторий, разработчики Git могут накапливать коммиты в своем локальном репозитории. Такой подход имеет множество преимуществ по сравнению с совместной работой в стиле SVN: он упрощает разделение функции на мелкие коммиты, объединение связанных коммитов и очистку локальной истории перед ее публикацией в центральном репозитории. Он также позволяет разработчикам работать в изолированной среде, откладывая интеграцию до тех пор, пока их наработки не будут готовы к слиянию с наработками других пользователей. Но хотя изоляция и отложенная интеграция удобны с точки зрения одного разработчика, при командной работе желательно выполнять интеграции часто и маленькими блоками. Для получения дополнительных рекомендаций по совместной работе в Git читайте, как команды разработчиков структурируют свой рабочий процесс в Git.

Отмена коммита с помощью git checkout

С помощью команды мы можем перейти к предыдущему коммиту, , и вернуть репозиторий в состояние, предшествовавшее этому безумному коммиту. Переход к отдельному коммиту приведет к тому, что в репозитории появится открепленный указатель HEAD. Работа при этом перестанет принадлежать какой-либо из веток. Когда указатель HEAD откреплен, все новые коммиты остаются без родителя при переходе обратно к стабильной ветке. «Сборщик мусора» в Git удаляет коммиты без родителя. Этот сервис работает с определенными интервалами и удаляет такие коммиты без возможности восстановления. Чтобы такие коммиты не были удалены «сборщиком мусора», перед их выполнением нужно убедиться, что мы работаем в ветке.

При наличии открепленного указателя HEAD можно выполнить команду . Она создаст новую ветку с именем и совершит переход в это состояние. Теперь репозиторий находится на новой временной шкале, где коммита не существует. На этом этапе мы можем продолжить работу в новой ветке, где коммита не существует и его можно считать «отмененным». Но к сожалению, если вам нужна предыдущая ветка (допустим, ), такая стратегия не подходит. Поэтому рассмотрим другие стратегии отмены. Более детальную информацию и примеры см. в нашей подробной статье о .

Изменение последнего коммита: git commit —amend

Команда — это удобный способ изменить последний коммит. Она позволяет объединить проиндексированные изменения с предыдущим коммитом без создания нового коммита. Ее также можно использовать для простого редактирования комментария к предыдущему коммиту без изменения состояния кода в нем. Но такое изменение приводит не только к редактированию последнего коммита, но и к его полной замене. Это означает, что измененный коммит станет новой сущностью с отдельной ссылкой. Для Git он будет выглядеть как новый коммит — на схеме ниже он отмечен звездочкой (*). Существует несколько распространенных сценариев использования команды . В следующих разделах мы приведем такие примеры.

Изменение комментария к последнему коммиту Git

Предположим, при выполнении коммита вы допустили ошибку в комментарии к нему. Выполнение этой команды в отсутствие проиндексированных файлов позволяет отредактировать комментарий к предыдущему коммиту без изменения состояния кода.

В процессе разработки регулярно случаются преждевременные коммиты. Очень просто забыть проиндексировать файл или использовать неправильный формат комментария к коммиту. Флаг позволяет без труда исправить эти небольшие ошибки.

Добавление опции позволяет передать новый комментарий из командной строки, не открывая текстовый редактор.

Изменение файлов после коммита

В следующем примере показан распространенный сценарий разработки с использованием Git. Допустим, вы отредактировали несколько файлов и хотите сделать коммит за одну операцию. Но потом выясняется, что вы забыли добавить один из файлов в самом начале. Чтобы исправить эту ошибку, достаточно проиндексировать другой файл и выполнить коммит с флагом :

Флаг позволяет внести изменения в коммит без изменения комментария к нему. Итоговый коммит заменит неполный коммит. При этом все будет выглядеть так, словно изменения в файлах и были сделаны за один коммит.

Не используйте amend для публичных коммитов

Измененные коммиты по сути представляют собой новые коммиты. При этом предыдущий коммит не остается в текущей ветке. Последствия этой операции аналогичны сбросу (reset) публичного состояния кода. Не изменяйте коммит, после которого уже начали работу другие разработчики. Эта ситуация только запутает разработчиков, и разрешить ее будет непросто.

Обзор

Если коротко, команда позволяет добавить новые проиндексированные изменения в последний коммит. С помощью коммита можно добавлять изменения в индекс Git или удалять таковые из него. Если никаких изменений не проиндексировано, при использовании флага вам все равно будет предложено изменить комментарий к последнему коммиту. Будьте осторожны при использовании флага с коммитами, доступными другим членам команды. Изменение коммита, доступного другому пользователю, может привести к путанице и длительным устранениям конфликтов при слиянии.

Аннотируемые теги

Аннотируемые теги хранятся в базе данных Git в виде полных объектов. Напомним, в них находятся дополнительные метаданные, такие как имя создателя тега, адрес электронной почты и дата. Аналогично комментариям к коммитам существуют комментарии к аннотируемым тегам. Кроме того, для обеспечения безопасности аннотируемые теги можно подписывать и проверять с помощью GNU Privacy Guard (GPG). Рекомендуется использовать аннотированные, а не облегченные теги, чтобы иметь доступ ко всем связанным метаданным.

При выполнении этой команды будет создан аннотируемый тег с идентификатором . Затем команда откроет настроенный текстовый редактор по умолчанию, чтобы запросить ввод дальнейших метаданных.

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

La red de seguridad: git reflog

Los registros de referencia («reflogs») son un mecanismo que Git utiliza para registrar las actualizaciones aplicadas a los extremos de las ramas y otras referencias de confirmaciones. El comando reflog te permite ir a una confirmación aunque no se haga referencia a esta en ninguna rama o etiqueta. Después de reescribir el historial, el registro de referencia contiene información sobre el antiguo estado de las ramas y te permite volver a ese estado, si es necesario. Cada vez que el extremo de tu rama se actualiza por cualquier motivo (intercambio de ramas, incorporación de nuevos cambios, reescritura del historial o adición de nuevas confirmaciones), se añade una nueva entrada al registro. En esta sección echaremos un vistazo al comando y exploraremos algunos de sus usos más frecuentes.

Uso

Este comando muestra el registro de referencia del repositorio local.

Así se muestra el registro de referencia con la información de fecha correspondiente (por ejemplo, hace dos semanas).

Ejemplo

Para comprender el comando , vamos a ver un ejemplo.

El registro de referencia anterior muestra que se ha cambiado de la rama maestra a la 2.2 y luego se ha vuelto. A partir de ahí, se ha aplicado un restablecimiento completo a una confirmación anterior. La actividad más reciente se representa en la parte superior denominada .

Si resulta que has retrocedido sin querer, el registro de referencia conservará la confirmación master apuntando a , como antes de que perdieras accidentalmente dos confirmaciones.

Con el comando git reset, ahora es posible cambiar la maestra a la confirmación anterior. Esto proporciona una red de seguridad en caso de que se haya modificado el historial por error.

Es importante tener en cuenta que el registro de referencia solo proporciona esta «red de seguridad» si los cambios se han confirmado en tu repositorio local, y que solo realiza el seguimiento de los movimientos del extremo de la rama del repositorio. Además, las entradas del registro tienen una fecha de vencimiento. El periodo de tiempo predeterminado antes del vencimiento de una entrada es de 90 días.

Para obtener más información, consulta la página sobre .

Git commit amend: A Beginner’s Guide

The git commit –amend command lets you modify your last commit. You can change your log message and the files that appear in the commit. The old commit is replaced with a new commit which means that when you amend your old commit it will no longer be visible in the project history.

Did you forget to include something in your last commit message? Did you make a typo? Did you add something into your commit message that is not relevant? Don’t worry! Git has a solution for you: the git commit –amend command.

In this guide, we’re going to talk about how to modify your last commit using the git commit –amend command. We’ll walk through an example to help you get started.

Summary

The command is one of the core primary functions of Git. Prior use of the command is required to select the changes that will be staged for the next commit. Then is used to create a snapshot of the staged changes along a timeline of a Git projects history. Learn more about usage on the accompanying page. The  command can be used to explore the state of the staging area and pending commit.

The commit model of SVN and Git are significantly different but often confused, because of the shared terminology. If you are coming to Git from a personal history of SVN usage, it is good to learn that in Git, commits are cheap and should be used frequently. Whereas SVN commits are an expensive operation that makes a remote request, Git commits are done locally and with a more efficient algorithm.