Как сделать изменения в коммите

Добавил пользователь Владимир З.
Обновлено: 05.10.2024

git config --global user.name "[name]" — установить имя, которое будет прикрепляться к коммиту.

git config --global user.email "[email address]" — установить email, который будет прикрепляться к коммиту.

git config --global color.ui auto — включить полезную подсветку командной строки.

git config --global push.default current — обновлять удаленную ветку с таким же именем, что и локальная, при пуше изменений (если не указано иного).

git config --global diff.tool [tool] — установить программу для разрешения конфликтов при слиянии.

Создание репозиториев

git init [project-name] — создать новый локальный репозиторий с заданным именем.

git clone [url] — загрузить проект и его полную историю изменений.

Работа с изменениями

git status — полный список изменений файлов, ожидающих коммита.

git status -s — краткий вид изменений.

git diff — показать изменения в файлах, которые еще не были добавлены в индекс коммита (staged).

git add [file] — сделать указанный файл готовым для коммита.

git add . — сделать все измененные файлы готовыми для коммита.

git add '*.txt' — добавить только файлы, соответствующие указанному выражению.

git add --patch filename — позволяет выбрать какие изменения из файла добавятся в коммит.

git diff --staged — показать что было добавленно в индекс с помощью git add , но еще не было закоммиченно.

git diff HEAD — показать что изменилось с последнего коммита.

git diff HEAD^ — показать что изменилось с предпоследнего коммита.

git diff [branch] — сравнить текущую ветку с заданной.

git difftool -d — то же самое, что и diff , но показывает изменения в заданной difftool.

git difftool -d master.. — показать изменения, сделанные в текущей ветке.

git diff --stat — показать статистику какие файлы были изменены и как.

git reset [file] — убрать файлы из индекса коммита (изменения не теряются).

git commit --amend — добавить изменения к последнему коммиту.

Работа с ветками

git branch — список всех локальных веток в текущей директории.

git branch [branch-name] — создать новую ветку.

git checkout [branch-name] — переключиться на указанную ветку и обновить рабочую директорию.

git checkout -b /
— переключиться на удаленную ветку.

git checkout [filename] — вернуть файл в первоначальное состояние если он еще не был добавлен в индекс коммита.

git merge [branch] — соединить изменения в текущей ветке с изменениями из заданной.

git merge --no-ff [branch] — соединить ветки без режима “fast forwarding”.

git branch -a — посмотреть полный список локальных и удаленных веток.

git branch -d [branch] — удалить заданную ветку.

git branch -D [branch] — принудительно удалить заданную ветку, игнорируя ошибки.

Работа с файлами

git rm [file] — удалить файл из рабочей директории и добавить в индекс информацию об удалении.

git rm --cached [file] — удалить файл из репозитория, но сохранить его локально.

git mv [file-original] [file-renamed] — изменить имя файла и добавить в индекс коммита.

Отслеживание файлов

.gitignore — текстовый файл, в котором задаются правила для исключения файлов из репозитория. Например:

git ls-files --other --ignored --exclude-standard — список всех игнорируемых файлов.

Сохранение фрагментов

git stash — положить во временное хранилище все отслеживаемые файлы.

git stash pop — восстановить последние файлы, положенные во временное хранилище.

git stash list — список всех сохраненных изменений во временном хранилище.

git stash drop — удалить последние файлы, положенные во временное хранилище.

Просмотр истории

git log — список изменения текущей ветки.

git log --follow [file] — список изменения текущего файла, включая переименования.

git log --pretty=format:"%h %s" --graph — изменение вида отображения истории изменений.

git log --author='Name' --after= --pretty=oneline --abbrev-commit — посмотреть над чем работал заданный пользователь последнюю неделю.

git log --no-merges master.. — посмотреть историю изменений только для текущей ветки.

git diff [file-branch]..[second-branch] — посмотреть различия между двумя заданными ветками.

git show [commit] — показать метадату и изменения в заданном коммите.

git show [branch]:[file] — посмотреть на файл в другой ветке, не переключаясь на неё.

Отмена коммитов

git reset — убрать изменения из индекса коммита, сами изменения останутся.

git reset [commit/tag] — отменить все коммиты после указанного коммита, изменения будут сохранены локально.

git reset --hard [commit] — принудительно вернутся к указанному коммиту, не сохраняя историю и изменения.

Синхронизация изменений

git fetch [bookmark] — загрузить всю историю с заданного удаленного репозитория.

git merge [bookmark]/[branch] — слить изменения локальной ветки и заданной удаленной.

git push — запушить текущую ветку в удаленную ветку.

git push [remote] [branch] — запушить ветку в указанный репозиторий и удаленную ветку.

git push [bookmark] :[branch] — в удаленном репозитории удалить заданную ветку.

git push -u origin master — если удаленная ветка не установлена как отслеживаемая, то сделать ее такой.

git pull — загрузить историю и изменения удаленной ветки и произвести слияние с текущей веткой.

git pull [remote][branch] — указать конкретную удаленную ветку для слияния.

git remote — посмотреть список доступных удаленных репозиториев.

git remote -v — посмотреть детальный список доступных удаленных репозиториев.

Я обычно представляю список коммитов на рассмотрение. Если у меня есть следующие коммиты:

. Я знаю, что могу изменить коммит с головой git commit --amend . Но как я могу изменить Commit1 , учитывая, что это не HEAD коммит?

Также вы можете просто посмотреть разделение коммита в Git Tools - Переписывание истории для получения дополнительной информации.

Вы можете использовать git rebase . Например, если вы хотите изменить коммит bbc643cd , запустите

Пожалуйста, обратите внимание на знак вставки ^ в конце команды, потому что на самом деле вам нужно перебазировать обратно в коммит, прежде чем тот, который вы хотите изменить .

В редакторе по умолчанию измените pick на edit в строке упоминание 'bbc643cd'.

Сохраните файл и выйдите: git будет интерпретировать и автоматически выполнять команды в файле. Вы окажетесь в предыдущей ситуации, в которой вы только что создали commit bbc643cd .

На данный момент bbc643cd это ваш последний коммит, и вы можете легко изменить его : внести изменения, а затем зафиксировать их с помощью команды:

После этого введите:

вернуться к предыдущему коммиту HEAD.

ВНИМАНИЕ : обратите внимание, что это изменит SHA-1 этого коммита, а также всех дочерних элементов - другими словами, это переписывает историю с этого момента. Делая это , вы можете сломать репо, если нажмете команду git push --force

Стоит отметить, что вам может потребоваться запустить git stash до git rebase и git stash pop после, если у вас есть ожидающие изменения.

Существует ли команда shortucut для редактирования определенного коммита в интерактивной перебазировке, не открывая редактор, не находя коммит, помечая его как редактирование, а затем возвращаясь в командную строку?

Обратите внимание, что с более новым git было бы разумнее следовать подсказкам, а не слепо использовать git commit --all --amend --no-edit здесь. Все, что я должен был сделать после этого, git rebase -i . - это git commit --amend нормально git rebase --continue .

Используйте удивительный интерактивный ребаз:

Найдите нужный коммит, измените pick на e ( edit ), сохраните и закройте файл. Git перемотает на этот коммит, что позволит вам:

  • использовать git commit --amend для внесения изменений, или
  • используйте git reset @~ для отмены последнего коммита, но не для изменений в файлах (т. е. перенесите вас в тот момент, когда вы редактировали файлы, но еще не зафиксировали).

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

Примечание: @ является сокращением для HEAD и ~ является коммитом перед указанным коммитом.

Не бойся перебазировать

* Остерегайтесь опций, как --hard и --force хотя - они могут отказаться от данных.
* Кроме того, не переписывайте историю ни в каких ветвях, над которыми вы сотрудничаете.

Во многих системах git rebase -i откроется Vim по умолчанию. Vim не работает, как большинство современных текстовых редакторов, поэтому взгляните на то, как сделать перебаз с помощью Vim . Если вы предпочитаете использовать другой редактор, измените его с помощью git config --global core.editor your-favorite-text-editor .

Середина вашего ответа - странное место для размещения того, что я могу описать только как рекламное объявление для VIM. Это не имеет отношения к вопросу и просто загромождает ваш ответ.

@Intentss: Ах, я понимаю, почему это выглядело странно. Причиной этого было то, что Vim является текстовым редактором по умолчанию во многих системах, поэтому первый опыт интерактивного перебазирования многих людей - это экран, на котором при наборе текста курсор перемещается повсюду. Затем они переключают свой редактор на что-то другое, и их второй опыт интерактивного перебазирования вполне нормален, но заставляет их задуматься, почему он использует текстовый файл вместо графического интерфейса. Чтобы добиться потока с помощью перебазирования, вам нужно что-то вроде Vim или Emacs 'rebase-mode.

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

Потрясающие! Я не знал, что вы могли бы использовать @ как сокращение для HEAD . Спасибо за публикацию этого.

Интерактивные перебазироваться с --autosquash то , что я часто использую , когда мне нужно FixUp предыдущих коммитов глубже в истории. Это существенно ускоряет процесс, который иллюстрирует ответ ZelluX, и особенно удобно, когда вам нужно отредактировать более одного коммита.

Предположим, у вас есть история, которая выглядит так:

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

Затем инициируйте интерактивную перебазировку коммита до

ваш редактор откроется с коммитами, уже правильно упорядоченными

все, что вам нужно сделать, это сохранить и выйти

$ git rebase --interactive commit_hash^

каждый ^ указывает, сколько коммитов вы хотите отредактировать, если он только один (указанный вами хэш, то вы просто добавляете один) ^ .

Если вы хотите выйти без применения изменений, нажмите :q!

РЕДАКТИРОВАТЬ : для навигации vim используйте j для перехода вверх, k вниз, h влево и l вправо (все это в NORMAL режиме, нажмите ESC для перехода в NORMAL режим). Чтобы редактировать текст, нажмите, i чтобы войти в INSERT режим, в который вы вставляете текст. Нажмите, ESC чтобы вернуться в NORMAL режим :)

ОБНОВЛЕНИЕ : Вот отличная ссылка из списка GitHub Как отменить (почти) все, что с Git

Что git push --force перезаписывает удаленные коммиты с вашими локальными коммитами. Это не относится к этой теме :)

@greenhouse, если вы измените и принудительно нажмете, то другие члены команды, скорее всего, столкнутся с конфликтами слияния. Так что вы должны быть очень осторожны с этим. Но если вы модифицируете что-то, что еще никто не получил, это должно быть хорошо (он этого не заметит). Поэтому я бы посчитал --force последней инстанцией и всегда консультировался с репо с другими участниками.

Если по какой-то причине вам не нравятся интерактивные редакторы, вы можете использовать git rebase --onto .

Скажи, что хочешь изменить Commit1 . Во-первых, ветвь из ранее Commit1 :

Во-вторых, возьмите Commit1 с собой cherry-pick :

Теперь внесите изменения, создав Commit1' :

И, наконец, после того, как вы спрятали любые другие изменения, перенесите остальные ваши коммиты master на верх вашего нового коммита:

Не забудьте убирать свои ветви!

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

Окончательно Force-push исправленных коммитов.

Полностью неинтерактивная команда (1)

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

Самым большим преимуществом этой команды является тот факт, что она не vim .

(1) учитывая, что нет никаких конфликтов во время перебазирования, конечно

Применение

Название amend-to кажется подходящим ИМХО. Сравните поток с --amend :

объяснение

  • git config --global alias. '! ' - создает глобальный псевдоним git, который будет выполнять не-git команду
  • f() < >; f - анонимная функция bash.
  • SHA=`git rev-parse "$1"`; - преобразует аргумент в git revision и присваивает результат переменной SHA
  • git commit --fixup "$SHA" Fixup-коммит для SHA . См git-commit документы
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" часть была покрыта другими ответами.
    • --autosquash это то, что используется в сочетании с git commit --fixup , см. git-rebase документы для получения дополнительной информации
    • GIT_SEQUENCE_EDITOR=true это то, что делает все это неинтерактивным. Этот взлом я узнал из этого поста в блоге .

    Автоматическое интерактивное редактирование ребазирования с последующим коммитом, готовым к повторному выполнению

    Я обнаружил, что исправляю прошлый коммит достаточно часто, поэтому я написал для него скрипт.

    Вот рабочий процесс:

    Это приведет вас к коммиту, который вы хотите отредактировать.

    Фиксируйте и ставьте коммит так, как вам хотелось бы.

    (Вы можете использовать git stash save любые файлы, которые вы не делаете)

    Повторите коммит --amend , например:

    Чтобы вышеперечисленное сработало, поместите приведенный ниже скрипт в исполняемый файл, который называется git-commit-edit где-то в вашем $PATH :

    Пришел к такому подходу (и он, вероятно, точно такой же, как с использованием интерактивного ребазинга), но для меня это довольно просто.

    Примечание: я представляю этот подход для иллюстрации того, что вы можете сделать, а не для повседневной альтернативы. Так как в нем много шагов (и, возможно, несколько предостережений).

    Скажем, вы хотите изменить коммит, 0 и вы в настоящее время на feature-branch

    Оформить заказ на эту фиксацию и создать quick-branch . Вы также можете клонировать свою функциональную ветвь как точку восстановления (перед запуском).

    Теперь у вас будет что-то вроде этого:

    Сценические изменения, прятать все остальное.

    Зафиксируйте изменения и вернитесь к feature-branch

    Теперь у вас будет что-то вроде этого:

    Перебазировать feature-branch на quick-branch (разрешить любые конфликты по пути). Примените тайник и удалите quick-branch .

    И вы в конечном итоге:

    Git не будет дублировать (хотя я не могу точно сказать, в какой степени) коммит 0 при ребазинге.

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

    Чтобы получить неинтерактивную команду, поместите скрипт с этим содержимым в ваш PATH:

    Используйте его, поставив свои изменения (с git add ), а затем запустите git fixup . Конечно, он все равно будет интерактивным, если у вас возникнут конфликты.

    Это хорошо работает. Я добавил некоторые дополнительные функции, чтобы делать частичные исправления грязного дерева для совершенствования набора коммитов. `dirtydiff = $ (git diff); if ["$ "! = ""]; затем эхо "Скрытое грязное дерево"> & 2; заначка; Fi;

    git stash + rebase автоматизация

    Когда мне нужно много раз модифицировать старый коммит для обзоров Геррита, я делаю:

    • изменить исходный файл, нет необходимости, git add если уже в репо
    • git-amend-old $old_sha

    Мне это нравится, --autosquash потому что это не раздавливает другие несвязанные исправления.

    Очень хороший обходной путь, это должна быть опция по умолчанию, git amend чтобы применить изменения к конкретному коммиту с использованием текущего тайника, очень умно!

    1) путем создания нового коммита с изменениями, которые я хочу ..

    2) я знаю, какой коммит мне нужно слить с ним. который совершает 3.

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

    4) здесь нам нужно изменить коммит, если вы хотите объединить с конкретным. это должно быть как,

    а затем сохранить свое дерево.

    Теперь слияние сделано с существующим коммитом.

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

    Теперь, как использовать эту команду?

    -i стенд для "интерактивного" . Обратите внимание, что вы можете выполнить ребаз в неинтерактивном режиме. например:

    HEAD указывает ваше текущее местоположение (может быть также именем филиала или коммитом SHA). ~n Означает «п beforeé, так HEAD~n будет список„п“фиксаций до того, вы в данный момент.

    git rebase имеет другую команду, как:

    Примечание: лучше сделать так, чтобы Git работал с вашим редактором кода, чтобы все было проще. Например, если вы используете визуальный код, вы можете добавить вот так git config --global core.editor "code --wait" . Или вы можете найти в Google, как связать предпочитаемый вами редактор кода с GIT.

    Пример git rebase

    Я хотел изменить последние 2 коммита, которые я сделал, поэтому я обрабатываю так:

    сохранить и закрыть.

    Желаю, чтобы это могло помочь новым пользователям :).

    Для меня это было для удаления некоторых учетных данных из репо. Я попытался перебазировать и столкнулся с кучей, казалось бы, не связанных между собой конфликтов, когда пытался перебазировать - продолжай. Не пытайтесь перебазировать себя, используйте инструмент под названием BFG (brew install bfg) на Mac.

    Если вы еще не выдвинули коммиты, вы можете вернуться к предыдущему коммиту, используя git reset HEAD^[1,2,3,4. ]

    Ой, забыл добавить file2 в первый коммит .

    Это добавит file2 к первому коммиту.

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

    Мой друг просто случайно натолкнулся на очень большие файлы (четыре автоматически сгенерированных файла размером от 3 до 5 ГБ каждый), а затем сделал еще несколько коммитов кода, прежде чем осознал проблему, которая больше git push не работала!

    Файлы были перечислены в списке, .gitignore но после переименования папки контейнера они были открыты и зафиксированы! И теперь было еще несколько коммитов кода поверх этого, но push он работал вечно (пытаясь загрузить ГБ данных!) И в конечном итоге потерпел неудачу из-за ограничений размера файлов Github .

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

    Итак, решение, которое я придумал, было:

    1. Переименуйте текущую папку git в ~/Project-old .
    2. Снова клонируйте папку git из github (в ~/Project ).
    3. Оформить заказ на ту же ветку.
    4. Вручную cp -r файлы из ~/Project-old папки в ~/Project .
    5. Убедитесь, что массивные файлы, которые не нужны для проверки, mv отредактированы и .gitignore правильно включены .
    6. Также убедитесь, что вы не перезаписываете .git папку в недавно клонированной ~/Project старой. Вот где живут журналы проблемной истории!
    7. Теперь просмотрите изменения. Это должен быть союз всех последних коммитов, исключая проблемные файлы.
    8. Наконец, внесите изменения, и это хорошо, когда вы будете push изданы.

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

    Большим преимуществом является то, что он очень понятен на каждом этапе, отлично работает с большими файлами (а также с чувствительными) и не оставляет следов в истории!


    Предполагается, что читатель этой статьи уже знаком с основами Git. Если это не так — сначала рекомендуется освоить базу, например, воспользовавшись этим материалом.

    Здесь мы рассмотрим несколько сценариев появления ошибок в коммитах и их исправления.

    Сценарий №1


    Сценарий №2

    Такой подход вполне имеет право на жизнь. Но для того, чтобы поддерживать историю коммитов в хорошем состоянии, вероятно, было бы куда лучше иметь возможность добавить случайно пропущенный файл в тот же коммит. Сделать это можно, опять же, командой git commit --amend . Выглядит её использование так:


    Сценарий №3

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

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



    Примечание

    Используйте команду amend только в своём локальном репозитории. Её применение в удалённых репозиториях может привести к огромной путанице.

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

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

    Каждый раз, когда вы загружаете код из удалённого в локальный репозиторий, в локальном репозитории создаётся новый коммит-слияние (Merge Commit). Это означает, что в вашей локальной истории коммитов будет много таких коммитов, которые могут запутать того, кто будет просматривать ваш код.


    Как привести в порядок историю коммитов? Для решения этой задачи можно воспользоваться командой git rebase .

    Рассмотрим команду git rebase на примере.


    В ветке Release есть три коммита: Rcommit1 , Rcommit2 , и Rcommit3 . Вы создали свою ветку Feature из ветки Release , когда в ней был всего один коммит — Rcommit1 . После этого вы добавили два коммита в ветку Feature . Это — Fcommit1 и Fcommit2 . Ваша цель заключается в том, чтобы загрузить коммиты из ветки Release в свою ветку Feature . Для того чтобы это сделать, вы собираетесь воспользоваться командой rebase .

    Будем использовать для двух рассматриваемых веток имена release и feature .

    В результате применение команды rebase будет выглядеть так:


    Команда rebase используется для того, чтобы обеспечить наличие в ветке Feature свежего кода из ветки Release .

    При применении этой команды система пытается добавить в ветку Feature каждый коммит, по одному, и осуществить проверку на наличие конфликтов. Если звучит это сложно — давайте рассмотрим следующий рисунок. Тут показаны внутренние механизмы команды rebase .


    Шаг 1

    В момент вызова команды ветка Feature указывает на голову ветки Release . После этого в ветке Feature оказывается три коммита: Rcommit1 , Rcommit2 , и Rcommit3 . Возможно, тут у вас появится вопрос о том, что случилось с коммитами Fcommit1 и Fcommit2 . Эти коммиты никуда не делись, они будут использованы на следующих шагах.

    Шаг 2

    Теперь Git пытается добавить коммит Fcommit1 в ветку Feature . При отсутствии конфликта Fcommit1 добавляется после Rcommit3 . При обнаружении конфликта Git сообщит об этом и вам придётся разрешить этот конфликт вручную.

    Шаг 3

    После того, как в ветку Feature добавлен коммит Fcommit1 , Git пытается добавить туда же Fcommit2 . Тут, опять же, если конфликтов нет, то Fcommit2 добавляется после Fcommit1 и операция оказывается успешно завершённой. Если обнаружен конфликт, то Git, как и прежде, сообщит об этом и предложит с ним разобраться.

    После завершения работы команды rebase можно будет увидеть, что в ветке Feature имеются коммиты Rcommit1 , Rcommit2 , Rcommit3 , Fcommit1 , и Fcommit2 .

    При работе с Git находят применение и команда merge , и команда rebase . Нельзя сказать, что одна из них предпочтительнее другой.

    В случае использования команды merge вы получите коммит-слияние. В случае использования rebase никаких дополнительных коммитов у вас не будет.

    Рекомендуется использовать эти команды в различных ситуациях. Так, rebase подходит для обновления кода локального репозитория на основе свежего кода из удалённого репозитория. Используйте команду merge , выполняя пулл-запросы, направленные на слияние ветки Feature с веткой Release или Master .

    Изучив представленные в этом материале концепции, вы улучшили свои навыки владения Git и приблизились к уровню Git-эксперта. Надеемся, то, что вы тут узнали, вам пригодится. Но мир Git огромен, поэтому, освоив что-то новое, не останавливайтесь на достигнутом и двигайтесь дальше.

    Видеоурок. Часть 1. Практика, основы работы с коммитами и историей коммитов

    Видеоурок. Часть 2. Практика, дополнительные приемы и фишки

    Видеоурок. Часть 3. Общие наблюдения и советы. Как делать "хорошие" коммиты

    Конспект урока

    Краткое содержание урока, основные инструкции для командной строки, полезные ссылки и советы.

    Что такое коммит

    По-научному это сохранение состояния, фиксация или слепок изменений.

    Чуть менее научно, коммит - зафиксированный набор изменений, который показывает, какие файлы изменились и что именно в них изменилось. Рассмотрим на примере.

    Как сделать коммит

    Представим, что мы добавляем блок учеников на сайт. Добавляем новую разметку в index.html и новые стили в main.css. Чтобы сохранить изменения, нужно их закоммитить. Но предварительно сообщить git, какие именно файлы мы хотим положить в коммит. Команда git add добавляет (или подготавливает) файлы к коммиту. Можно добавить файлы по отдельности, вот так

    А можно все сразу

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

    Создаем сам коммит

    Состояние файлов в git. Измененные и подготовленные файлы

    Измененные файлы - это те файлы, которые мы успели изменить с момента последнего коммита

    Подготовленные файлы отличаются от измененных тем, что они "подготовлены" к коммиту, то есть будут добавлены в следующий коммит.

    git add filename добавляет или подготавливает файл к коммиту.
    git reset filename удаляет файл из подготовленных к коммиту.

    Содержимое файлов при этом не меняется. Один файл может одновременно находиться и в измененных, и в подготовленных. Это происходит, если мы добавили файл, но не закоммитили и продолжили делать в нем измения.

    Из чего состоит коммит

    Каждый коммит имеет

    Как добавить файлы и сделать коммит одной командой

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

    Отслеживаемые и неотслеживаемые файлы

    Отслеживаемые файлы - это те, в которых git отлавливает изменения и показывает их через git status и git diff. В нашем проекте файлы index.html и css/main.css - отслеживаемые.

    Неотслеживаемые файлы - это файлы, изменения в которых git не отлавливает. Новый файл в проекте по умолчанию попадает в неотслеживаемые. Добавить новый файл в рабочую область git можно командой git add filename

    История коммитов, git log

    Все коммиты можно посмотреть в истории коммитов. История хранит все данные обо всех коммитах проекта. Показывается история командой

    История включает в себя все сведения о коммитах: хэш, автор, дата и список изменений. Список изменений смотреть командой git show по хэшу коммита

    Переименование последнего коммита, git commit --amend

    Если коммит успели запушить, то переименовывать коммиты нужно осторожно, как именно - во второй части курса.

    Откат коммитов, git revert

    Если мы сделали неверный коммит и хотим откатить изменения, сделанные в нем, то поможет команда git revert

    При этом откроется дефолтный текстовый редактор, который предолжит ввести commit message. Если мы хотим оставить commit message по умолчанию, то можно обойтись без открытия редактора с помощью флажка --no-edit

    Работа с файлами

    При работе с файлами нужно учесть, что новые файлы git отправляет в неотслеживаемые. Поэтому при добавлении нового файла стоит сначала его закоммитить, а потом вносить изменения, чтобы они были доступны через git diff

    При обычном переименовании файла в файловом менеджере или командой mv git сначала показывает 2 файла: старый удаленный и новый неотслеживаемый. Чтобы git понял, что этот файл именно переименованный, нужно сначала добавить эти файлы в подготовленные к коммиту

    Тогда при команде git status файл будет отображаться именно как переименованный

    Можно избежать этого промежуточного состояния, если переименовать файл в командной строке таким образом

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

    Командная строка vs IDE

    Работа в PhpStorm продемонстрирована в первых двух частях видео.

    Как и в прошлом уроке мы видим, что некоторые вещи удобнее делать в IDE. Например, процесс добавления файлов (git add) в PhpStorm при создании коммита почти не привлекает внимания. Но важно понимать, что такое git add и зачем он нужен. И что любая IDE под капотом все равно выполняет базовые команды git. Просто для нас предоставляется удобная обертка, чтобы мы больше сосредоточились на самом проекте, а не на git.

    Наблюдения и советы при работе с коммитами

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

    • коммит - это законченный функционал
    • всегда проверяйте перед коммитом, что в него попадет. git diff - наш лучший друг
    • выделяйте мелкие баги и правки в отдельные коммиты
    • маленький коммит в одну строку - это нормально
    • видите много изменений - подумайте, можно ли разбить их на отдельные коммиты
    • мыслите задачей, а не файлами. Выделяйте полезное действие коммита
    • commit message говорит, ЧТО делает коммит, а не КАК делает
    • коммит-рефакторинг - это нормально. Не стоит мешать его с другими задачами
    • git плохо работает с бинарниками (картинками, pdf, видеофайлами) - видит факт изменения, но не сами изменения
    • подписывайте коммит так, чтобы можно было проследить историю развития проекта

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

    Используйте удобные инструменты в IDE, но не забывайте командную строку. В ней вы лучше будете понимать, как устроен git, как он работает

    Хорошие и плохие коммиты

    С точки зрения git коммиты не бывают плохими и хорошими. Но есть удачные и неудачные подписи к коммитам с точки зрения наших коллег. Несколько примеров

    Изменен файл index.html
    Добавлен блок новостей
    В первом коммите непонятно, что он делает, во втором - ясно описана задача

    Изменены стили баннера
    Растянули баннер на всю ширину окна
    Первый коммит говорит только об изменениях стилей баннера, второй - точно, что именно изменено. Больше информации

    Добавлен файл VipClient
    Работа с vip-клиентами вынесена в отдельный класс
    По первому коммиту можно предположить, что в VipClient мы скорее всего работаем с ВИПами. Во втором коммите это точно понятно, плюс дополнительная информация, что это отдельный класс.

    Поправлены стили в main.css
    Рефакторинг стилей в main.css
    Первый коммит говорит о правке стилей, но непоянтно, что именно поправлено. Бага? Новые значения? Изменен цвет текста по рекомендации дизайнера? Второй коммит ясно указывает, что это рефакторинг

    Маленький фикс
    Исправлена опечатка в заголовке title страницы "О компании"
    Коммит "маленький фикс" даже приблизительно не говорит, в чем он заключается. Второй коммит дает полное представление

    Немного о философии коммитов

    Концепция коммитов заставляет если не менять подход к разработке, то по-другому к ней относиться. С git нам приходится не просто писать код, а планировать его написание. Планировать задачи, над которыми мы работаем. Декомпозировать задачи, то есть разбивать их на небольшие части.

    Мы больше думаем о том, что мы работаем не одни, а в команде. История коммитов общая для всего проекта. Чем лучше мы научимся формировать и подписывать коммиты, тем легче будет ориентироваться в истории нам самим и нашим коллегам.

    В любом проекте важны не только код и его структура, но и история коммитов и хорошие commit message.

    git good commit message

    На этом все. В следующем уроке мы будем больше работать с историей коммитов и посмотрим различные варианты использования команды git log

    Читайте также: