Разное

Git посмотреть изменения в коммите: как посмотреть изменения, внесенные определенным коммитом

Содержание

как посмотреть изменения, внесенные определенным коммитом

Посмотреть изменения, внесенные коммитом, можно с помощью двух команд: git show и git log -p.

Команда:

git show <коммит>

показываеет изменения, внесенные указанным коммитом.

Команда git log -p служит чтобы просмотреть сразу несколько коммитов. Выдержка из ProGit:

Один из наиболее полезных параметров команды git log — это -p, который показывает дельту (т. е. разницу, представленную в формате diff), привнесенную каждым коммитом.

Если вы хотите увидеть не весь лог, а только часть, вы также можете использовать числовую опцию, например -2, что ограничит вывод до 2-х последних записей. Пример:

$ git log -p -2

commit ca82a6dff817ec66f44342007202690a93763949

Author: Scott Chacon <[email protected]>

Date: Mon Mar 17 21:52:11 2008 -0700

changed the version number

diff —git a/Rakefile b/Rakefile

index a874b73..8f94139 100644

— a/Rakefile

+++ b/Rakefile

@@ -5,5 +5,5 @@ require ‘rake/gempackagetask’

spec = Gem::Specification.new do |s|

s.name = «simplegit»

— s.version = «0.1.0»

+ s.version = «0.1.1»

s.author = «Scott Chacon»

s.email = «[email protected]

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7

Author: Scott Chacon <[email protected]>

Date: Sat Mar 15 16:40:33 2008 -0700

removed unnecessary test code

diff —git a/lib/simplegit.rb b/lib/simplegit.rb

index a0a60ae..47c6340 100644

— a/lib/simplegit.rb

+++ b/lib/simplegit.rb

@@ -18,8 +18,3 @@ class SimpleGit

end

end

-if $0 == __FILE__

— git = SimpleGit.new

— puts git.show

-end

\ No newline at end of file

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

История коммитов в подробностях. Урок 5

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

Видеоурок

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


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

Для информации


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

История коммитов


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

Команда git log


За просмотр истории коммитов отвечает команда git log. В сочетании с различными параметрами эта команда выводит историю по-разному.
Есть много различных вариантов и комбинаций параметров, посмотрим некоторые из них

git log, просмотр истории по умолчанию


    $ git log


Показывает все коммиты от новых к старым. Для каждого коммита выводится

  • хэш
  • автор
  • дата
  • сообщение (commit message)

git log -p, расширенный вывод истории


    $ git log -p


Выводит то же, что и git log, но еще и с изменениями в файлах

git log —oneline, короткая запись


    $ git log --oneline


Вывод коммитов в одну строку. Показывает только хэш коммита и commit message

git log —stat —graph, история в виде дерева


    $ git log --stat --graph


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

Сортировка и фильтрация истории


Есть множество команд, которые позволяют сортировать и фильтровать историю коммитов в командной строке. В том числе в сочетании с линуксовыми командами.
Рассмотрим некоторые из них

Поиск по коммитам


Команда grep — мощный инструмент, который помогает работать в том числе и с git. Например, искать по коммитам


    git log --oneline | grep revert # поиск упоминания revert
    git log --oneline | grep -i revert # независимо от регистра

Коммиты, затронувшие один файл


    git log index.html

Поиск по автору


    git log --author webdevkin


В опции —author можно указать имя или email, необязательно целиком, можно только часть.

Поиск по диапазону дат


Опции —after и —before задают начальную и конечную даты коммитов


     git log --after='2020-03-09 15:30' --before='2020-03-09 16:00'

Комбинация команд и опций


Команды и опции git можно комбинировать и дополнять их линуксовыми командами


    git log --author=webdevkin --oneline | grep footer # все коммиты от автора, в которых упоминается footer
    git log --oneline | wc -l # количество коммитов

Какие еще есть варианты


Мы рассмотрели базовые примеры, но в документации по git log есть много различных опций.
Все их рассматривать нет смысла, при необходимости изучайте документацию.


    git log --help

Просмотр отдельного коммита, git show


Чтобы просмотреть отдельный коммит, нужно узнать его хэш. Хэш коммита выводится в любой команде git log, с параметрами или без. Например,


    $ git log --oneline
    
    7b7d7fa Fixed footer
    26812f9 Revert "Fixed footer"
    0f90ae7 Revert "Fixed styles"
    ...
    a1f3c45 Added footer
    a65aa43 Added new block students to main page
    0b90433 Initial commit


Смотрим второй коммит


    $ git show 43f6afc


Выводится подробная информация о коммите:

  • хэш
  • автор
  • дата
  • commit message
  • список измененных файлов
  • изменения в каждом файле

Короткий хэш коммита


Хэш коммита 40-символьный, но можно использовать короткую запись — первые 7 символов хэша.
Команда git log —oneline выводит именно короткий хэш. Для других операций с коммитами достаточно использовать первые 4 символа.
Например, 3 команды ниже покажут содержимое одного и того же коммита


    $ git show 051f75475cb1dca3cd08c1c7367a3308671ccf7b
    $ git show 051f754
    $ git show 051f

История коммитов в PhpStorm


В окне Local Changes, на вкладке Log показывается вся история коммитов, в левой половине вкладки. В списке коммитов показываются их commit message, автор и дата.
Клик на нужный коммит откроет в правой части вкладки список измененных файлов. Клик на нужном файле и Ctrl/Cmd+D покажет все изменения в этом файле точно так же, как и git diff.


В тексте объяснить работу с историей в PhpStorm сложно, смотрите видеоурок.

Переключение на старый коммит, зачем это нужно


Нужно это обычно в двух случаях:


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


2. При отладке. Когда в код закралась бага и мы постепенно продвигаемся «назад в прошлое» и ищем, в какой момент что-то сломалось

Как переключиться на коммит в терминале


Первое — узнать хэш нужного коммита. Например, имеем такую историю


    $ git log --oneline
    
    7b7d7fa Fixed footer
    26812f9 Revert "Fixed footer"
    0f90ae7 Revert "Fixed styles"
    ...
    a1f3c45 Added footer
    a65aa43 Added new block students to main page
    0b90433 Initial commit


Хотим переключиться на предпоследний коммит. Коммиты идут в порядке убывания, поэтому нам нужен второй сверху — 26812f9. Переключаемся на него командой


    $ git checkout 26812f9


Все, вернулись в прошлое. Проверим историю, теперь коммит, на который мы переключились — последний


    $ git log --oneline 
    
    26812f9 Revert "Fixed footer"
    0f90ae7 Revert "Fixed styles"
    ...
    a1f3c45 Added footer
    a65aa43 Added new block students to main page
    0b90433 Initial commit


Уйдем еще дальше, переключимся на первый коммит. Так как коммиты упорядочиваются по убыванию даты, то первый коммит — это последний в списке — 0b90433 Initial commit


    $ git checkout 0b90433


Проверяем историю


    $ git log --oneline 
    
    0b90433 Initial commit


Чтобы вернуться обрано, в исходное состояние, нужно набрать


    $ git checkout master


master — это ветка, в которой мы работаем по умолчанию. О ветках поговорим через пару уроков

Как переключаться между коммитами в PhpStrom


Вкладка Log, правый клик на нужном коммите и Checkout Revision. Все. История коммитов будет видна по-прежнему вся, но напротив текущего коммита будет стоять значок HEAD с символом «!»


Как вернуться обратно? В правом нижем угле PhpStorm есть пункт git:, кликаем на него, выбираем Local Branches — master — checkout. Значок «!» пропадет — мы вернулись в исходное состояние

Что могу посоветовать

  • как и git diff, историю коммитов git log удобнее смотреть в PhpStorm
  • в команде git log есть множество вариантов сортировки и фильтрации
  • сочетание git log с простыми линуксовыми командами дает хороший эффект. Обычный grep — очень хороший помощник
  • PhpStorm предоставляет удобные возможности по фильтрации коммитов. Можно искать коммиты по commit message, по автору, дате и по папкам, в которых происходили изменения
  • перемещайтесь по истории осторожно, не забывайте возвращаться в исходное состояние


На этом все. В следующем уроке мы поговорим о взаимодействии с сервером и познакомимся с командами git push и git pull.


Спасибо за внимание и до встречи!

Все уроки курса

Продолжение следует…

19 советов по повседневной работе с Git / Блог компании Mail.ru Group / Хабр

Если вы регулярно используете Git, то вам могут быть полезны практические советы из этой статьи. Если вы в этом пока новичок, то для начала вам лучше ознакомиться с Git Cheat Sheet. Скажем так, данная статья предназначена для тех, у кого есть опыт использования Git от трёх месяцев. Осторожно: траффик, большие картинки!

Содержание:

  1. Параметры для удобного просмотра лога
  2. Вывод актуальных изменений в файл
  3. Просмотр изменений в определённых строках файла
  4. Просмотр ещё не влитых в родительскую ветку изменений
  5. Извлечение файла из другой ветки
  6. Пара слов о ребейзе
  7. Сохранение структуры ветки после локального мержа
  8. Исправление последнего коммита вместо создания нового
  9. Три состояния в Git и переключение между ними
  10. Мягкая отмена коммитов
  11. Просмотр диффов для всего проекта (а не по одному файлу за раз) с помощью сторонних инструментов
  12. Игнорирование пробелов
  13. Добавление определённых изменений из файла
  14. Поиск и удаление старых веток
  15. Откладывание изменений определённых файлов
  16. Хорошие примечания к коммиту
  17. Автодополнения команд Git
  18. Создание алиасов для часто используемых команд
  19. Быстрый поиск плохого коммита

1. Параметры для удобного просмотра лога

Пример команды: git log —oneline —graph

Скорее всего, вам уже доводилось использовать команду git log. У неё есть много полезных параметров, которые можно комбинировать друг с другом для достижения наилучшего результата. Чаще всего я использую эти:

  • —author=»Alex Kras» — выводит коммиты, сделанные конкретным человеком
  • —name-only — выводит только названия изменённых файлов
  • —oneline — выводит сокращённые данные коммита (в виде одной строки)
  • —graph — выводит дерево зависимостей для всех коммитов
  • —reverse — выводит коммиты в обратном хронологическом порядке (сначала старые)
  • —after — выводит коммиты, сделанные после определённой даты
  • —before — выводит коммиты, сделанные до определённой даты

К примеру, когда-то у меня был руководитель, который требовал еженедельные отчёты каждую пятницу. И мне было достаточно написать git log —author=»Alex Kras» —after=»1 week ago» —oneline, немного подредактировать полученный результат и отправить их начальству.

Вообще, в Git есть много всяких полезных параметров. Просто попробуйте выполнить man git-log чтобы посмотреть все варианты просмотра истории. Если ни один из предложенных вариантов вас не устроит, вы всегда можете воспользоваться параметром —pretty, с помощью которого можно настраивать выдачу в широких пределах.

2. Вывод актуальных изменений в файл

Пример команды: git log -p filename

С помощью команд git log -p или git log -p filename можно посмотреть не только примечание к коммиту, автора и дату, но также сделанные в этом коммите изменения.

Далее можно использовать функцию поиска утилиты less, набрав «слеш» и введя поисковый запрос: /{{поисковый-запрос}} (используйте маленькую «n» для перехода к следующему результату поиска и большую «N» для того, чтобы вернуться к предыдущему):

3. Просмотр изменений в определённых строках файла

Пример команды: git log -L 1,1:some-file.txt

С помощью команды git blame filename можно определить автора последних изменений для каждой строки в файле.

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

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

По сути это аналог команды git log -p, только с фокусом на конкретных изменениях.

4. Просмотр ещё не влитых в родительскую ветку изменений

Пример команды: git log —no-merges master..

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

Команда git log —no-merges master.. решает эту проблему: параметр —no-merges говорит, что нужно показать коммиты, которые ещё не были вмёржены куда-либо, а параметр master.. говорит, что нужно показать только те изменения, которые ещё не были вмёржены в ветку master (здесь важно обратить внимание на две точки после названия ветки).

Чтобы посмотреть не только коммиты, но и изменения, которые были в них внесены, можно использовать команды git show —no-merges master.. или git log -p —no-merges master.. (их вывод будет идентичным).

5. Извлечение файла из другой ветки

Пример команды: git show some-branch:some-file.js

Иногда бывает удобно посмотреть на какой-либо файл в другой ветке, не переключаясь на неё. Это можно сделать с помощью команды git show some-branch-name:some-file-name.js, которая выведет содержимое файла в указанной ветке прямо в терминал.

А с помощью перенаправления вывода можно сохранить этот файл в указанное место на диске, например, если вы заходите открыть два файла одновременно в своём редакторе: git show some-branch-name:some-file-name.js > deleteme.js.

Примечание: если вам нужно всего лишь сравнить два файла, то можно выполнить такую команду: git diff some-branch some-filename.js

6. Пара слов о ребейзе

Пример команды: git pull —rebase

Ранее мы говорили о многочисленных мёржах мастера в рабочую ветку. Некоторых из них можно избежать, используя команду git rebase. Вообще, ребейз — очень мощная функция, и, пожалуй, будет лучше оставить её подробное описание для отдельного поста. Вот, например, что говорится в книге «Pro Git»:

Несмотря на все свои преимущества, у ребейза есть и свои недостатки, которые можно выразить одним предложением:

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

Если вы последуете этому совету, то всё будет хорошо. В противном случае все будут вас ненавидеть, а друзья и семья станут вас презирать.

Однако ребейза не нужно бояться, просто следует соблюдать осторожность при работе с ним.

Пожалуй, лучший способ сделать ребейз — использовать его интерактивный режим, запускаемый с помощью команды git rebase -i {{some commit hash}}, которая откроет редактор с инструкциями о том, что и как делать. Не буду дальше вдаваться в подробности, поскольку тема эта достаточно объёмная.

Ещё одна полезная команда ребейза: git pull —rebase

Например, вы работаете с локальной копией ветки и сделали небольшой коммит. А в это время кто-то ещё залил в удалённую копию ветки результаты своего недельного труда. Когда вы попытаетесь запушить свои изменения, Git скажет вам, что он не может это сделать, и что вам сначала нужно сделать git pull для разрешения конфликта. Как добропорядочный человек вы так и поступите и после выполнения команды git pull в истории вашей локальной копии ветки получится вот такой вот коммит, сгенерированный автоматически: «Merge remote-tracking branch ‘origin/master’».

Это, конечно, не проблема и всё будет работать как нужно, однако такие коммиты засоряют историю изменений. В таких случаях лучше выполнять команду git pull —rebase, и Git сначала заберёт изменения из удалённой копии ветки, а потом накатит ваши незапушенные коммиты после самого последнего коммита удалённой ветки, так, как будто бы всё так и было. Таким образом необходимость мёржа отпадает и мы избежим уродливого коммита о мёрже в истории изменения.

7. Сохранение структуры ветки после локального мержа

Пример команды: git merge —no-ff

Мне нравится создавать новую ветку для каждого нового багфикса или фичи. Помимо прочего, это помогает чётко понимать, как серия коммитов связана с конкретным таском. Если вы когда-либо мёржили пул-реквесты на гитхабе или похожих сервисах, у вас всегда была возможность посмотреть подробную историю смёрженной ветки с помощью команды git log —oneline —graph.

Если вы когда-либо мёржили локальные ветки друг с другом, то вы могли заметить, что Git выравнивает историю коммитов, располагая их линейно один за другим. Для того, чтобы избежать этого и оставить историю изменений древовидной (такой, как после пул-реквеста), вы можете добавить параметр —no-ff, и в итоге получится подробная древовидная история: git merge —no-ff some-branch-name

8. Исправление последнего коммита вместо создания нового

Пример команды: git commit —amend

Этот совет очень простой. Допустим, вы сделали изменения, закоммитили их, а потом обнаружили опечатку. Вы можете сделать новый коммит с описанием «исправление опечатка», но есть вариант получше.

Если вы ещё не запушили изменения в удалённую ветку, то можно сделать вот так вот:

  1. Исправьте ошибку.
  2. Добавьте изменения в список файлов, подготовленных для коммита: git add some-fixed-file.js.
  3. Запустите команду git commit —amend, которая добавит эти последние изменения в самый последний коммит. Вы так же сможете отредактировать примечание к коммиту.
  4. Когда всё будет готово, вы можете запушить ветку в удалённый репозиторий.

Если вы работаете над веткой один, то вы можете исправить изменения даже после того, как вы запушили ветку в удалённый репозиторий. Просто выполните git push -f после внесения изменений, и удалённая ветка будет перезаписана. Но вам НЕ ЗАХОЧЕТСЯ делать это с веткой, с которой работают другие люди (как обсуждалось в совете про ребейз выше). В таких случаях, возможно, лучший вариант — новый коммит с примечанием «исправление опечатки».

9. Три состояния в Git и переключение между ними

Пример команды: git reset —hard HEAD и git status -s

Как вы, наверное, уже знаете, файл в Git может находится в одном из трёх состояний:

  1. unstaged — не добавлен в индекс для коммита
  2. staged — добавлен в индекс для коммита
  3. commited — закоммичен

(На самом деле есть ещё, как минимум, статус untracked — файл не добавлен в репозиторий — прим. перев.).

С помощью команды git status вы можете получить подробное описание файлов и их состояний. Чтобы добавить файл в индекс для коммита (перевести его из состояния unstaged в состояние staged), нужно выполнить команду git add filename.js. Команда git add . добавляет сразу все файлы (в текущей директории — прим. перев.).

Для более быстрого и простого просмотра состояния файлов можно воспользоваться командой git status -s, результат будет выглядеть примерно так:

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

Есть ещё несколько команд для переключения состояния файлов.

Сброс состояния файлов

Сброс позволяет откатиться на определённую версию в истории изменений Git. Всего есть три вида сброса:

  1. git reset —hard {{some-commit-hash}} — вернуться на определённый коммит в истории. Все изменения, сделанные после этого коммита пропадут.
  2. git reset {{some-commit-hash}} — вернуться на определённый коммит в истории. Все изменения, сделанные после этого коммита, получат состояние «Not staged for commit». Чтобы вернуть их обратно, нужно использовать команды git add и git commit.
  3. git reset —soft {{some-commit-hash}} — вернуться на определённый коммит в истории. Все изменения, сделанные после этого коммита, получат состояние «Staged for commit». Чтобы вернуть их обратно, нужно использовать команду git commit.

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

  1. Если я хочу отменить все внесённые изменения и начать работу с чистого листа, я использую команду git reset —hard HEAD (самый частый случай).
  2. Если я хочу отредактировать изменения и/или закоммитить файлы в другом порядке, я использу git reset {{some-start-point-hash}}.
  3. Если я просто хочу взять три последних коммита и слить их в один большой коммит, я использую команду git reset —soft {{some-start-point-hash}}.

Выгрузка отдельных файлов

если вам нужно отменить некоторые локальные изменения для конкретных файлов, но при этом изменения для других файлов трогать не нужно, гораздо проще забрать закоммиченные изменения этих файлов с помощью команды git checkout forget-my-changes.js. Это как git reset —hard, только для конкретного файла.

Также можно забирать разные версии файла из других коммитов или веток: git checkout some-branch-name file-name.js и git checkout {{some-commit-hash}} file-name.js.

Обратите внимание, что выгруженные файлы будут находиться в состоянии «Staged for commit», и чтобы убрать их из индекса для коммита нужно будет использовать команду git reset HEAD file-name.js. Для возврата в исходное состояние просто наберите git checkout file-name.js ещё раз.

Обратите внимание, что команда git reset —hard HEAD file-name.js не сработает. В целом процедура смены состояний в Git несколько запутана и не всегда можно сходу понять, что и как нужно сделать. Я надеюсь, что в этом совете я доступно и понятно всё объяснил.

10. Мягкая отмена коммитов

Пример команды: git revert -n

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

Обычный git revert автоматически закоммитит те изменения, которые откатили, запросив у вас примечание к новому коммиту отката. Флаг «-n» говорит гиту, чтобы тот не переживал по поводу срочного коммита новых изменений, ведь мы хотим просто посмотреть на них.

11. Просмотр диффов для всего проекта (а не по одному файлу за раз) с помощью сторонних инструментов

Пример команды: git difftool -d

Моя любимая программа для сравнения файлов в графическом интерфейсе — Meld. Я влюбился в неё ещё со времён Linux, и с тех пор она всегда со мной.

Я, кстати, не пытаюсь пропагандировать Meld. Скорее всего, у вас уже есть любимая программа для сравнения файлов, и, вероятнее всего, она умеет работать с Git, как для сравнения, так и для разрешения конфликтов. Просто запустите следующие команды, заменив «meld» на свою любимую утилиту:

git config --global diff.tool meld
git config --global merge.tool meld

После этого всё, что вам нужно — запустить команду git difftool some-file.js для просмотра изменений в соответствующей программе вместо консоли.

Однако некоторые программы (например, тот же meld) поддерживают сравнение не только файлов, но и директорий. Если вы запустите команду git difftool -d, то увидите дифф по всему проекту, и иногда это бывает полезно.

12. Игнорирование пробелов

Пример команды: git diff -w или git blame -w

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

К счастью, Git достаточно умён, чтобы понимать, что к чему. Вы можете запускать многие команды (такие, как git diff, git blame и т.д.) с флагом «-w» и Git будет просто игнорировать все изменения, связанные с пробельными символами (пробел, табуляция и другие).

13. Добавление определённых изменений из файла

Пример команды: git add -p

Кто-то из разработчиков Git явно неравнодушен к флагу «-p«, поскольку обычно он добавляет очень удобные штуки к различным командам.

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

14. Поиск и удаление старых веток

Пример команды: git branch -a

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

Все ветки репозитория можно посмотреть с помощью команды git branch -a (ключ «-a» выведет все ветки, в том числе из удалённого репозитория), а параметр —merged покажет только те ветки, которые были вмёржены в ветку master.

Скорее всего, вы захотите сперва запустить команду git fetch -p (получить изменения из удалённого репозитория и удалить неактуальные данные), чтобы убедиться, что вы работаете с актуальными данными.

Можно изощриться и вывести списки всех удалённых веток, комментарии к последним коммитам в них и дату последних изменений:

git for-each-ref --sort=committerdate --format='%(refname:short) * %(authorname) * %(committerdate:relative)' refs/remotes/ | column -t -s '*'

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

15. Откладывание изменений определённых файлов

Пример команды: git stash —keep-index или git stash -p

Если вы ещё не знаете, что делает команда git stash, то она просто кладёт все незакоммиченные изменения в специальный стек Git. Потом вы в любой момент можете выполнить git stash pop и применить все эти изменения назад. Вы так же можете посмотреть список всех сохранённых состояний в стеке с помощью команды git stash list, для более подробной информации посмотрите справку: man git-stash.

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

Помните магический ключ «-p«? У команды git stash он тоже есть, и, как вы уже, наверное, догадались, этот при использовании этого ключа Git предложит вам выбрать те изменения, которые нужно отложить.

Обязательно попробуйте нажать «?«, чтобы посмотреть список всех возможных опций.

Есть ещё один способ отложить только те файлы, которые нужно:

  1. С помощью команды git add добавьте в индекс для коммита те файлы, которые вы не хотите откладывать (например: git add file1.js, file2.js)
  2. Выполните git stash —keep-index, и Git отложит те файлы, которые не были добавлены в индекс для коммита
  3. Выполните git reset чтобы сбросить индекс и продолжите работу

16. Хорошие примечания к коммиту

По этой теме можно посоветовать замечательную статью «Как писать примечания к коммитам».

Здесь же я хочу особо подчеркнуть одно важное правило: хорошее примечание к коммиту должно заканчивать следующее предложение: «После применения данный коммит {{ текст вашего примечания }}». Например:

  • После применения данный коммит обновляет файл readme
  • После применения данный коммит добавляет валидацию вызова GET /user/:id API
  • После применения данный коммит отменяет коммит 12345

17. Автодополнения команд Git

Для некоторых операционных систем (например, Ubuntu), автодополнение для Git в шелле включено по умолчанию. Если в вашей операционной системе это не так (а в Mac OS X это не так), вы легко можете включить автодополнение.

18. Создание алиасов для часто используемых команд

TL;DR: используйте алиасы Git или bash для наиболее часто используемых команд Git.

Лучше всего работать с Git через командную строку. А лучший способ освоиться с командной строкой — каждый раз делать всё в полном объёме (набирать длинные команды). Однако рано или поздно приходит желание создать более короткие и удобные алиасы, чтобы не вводить каждый раз одни и те же команды.

Git имеет встроенную систему алиасов, например, если вы выполните следующую команду:

git config --global alias.l "log --oneline --graph"

Будет создан новый алиас для Git с названием «l«, и это позволит вам набирать git l вместо git log —oneline —graph.

Примечание: к алиасам Git можно так же добавлять дополнительные параметры (например, git l —author=»Alex»).

Альтернатива алиасам гита — старые добрые алиасы Bash. Например, в моём конфиге .bashrc есть такая строка: alias gil=»git log -online -graph», которая позволяет мне писать gil вместо полной длинной команды, и кроме того, это на целых два символа меньше, чем git l :).

19. Быстрый поиск плохого коммита

Пример команды: git bisect

Команда git bisect использует принцип «разделяй и властвуй» для поиска плохого коммита в большой истории изменений.

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

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

Вот второй вариант — это именно тот случай, когда пригождается команда git bisect. Она позволяет вам найти плохой коммит в кратчайшие сроки.

Так что же делает git bisect?

После того, как вы укажете коммит, в котором ничего не работает («плохой» коммит) и коммит, в котором всё работает («хороший» коммит), git bisect разделит все коммиты, которые располагаются между ними пополам, переключится в новую (безымянную) ветку на этом срединном коммите и позволит вам проверить, работает ли в нём ваша фича.

Предположим, в этом «срединный» коммите всё работает. Тогда вы говорите об этом гиту с помощью команды git bisect good и у вас останется только половина всех коммитов для поиска того самого, поломавшего всё.

После выполнения этой команды Git разделит оставшиеся коммиты пополам и снова переключится в безымянную ветку на новом срединном коммите, позволив вам протестировать работоспособность вашей фичи. И так далее, пока вы не обнаружите тот самый «плохой» коммит.

Благодаря тому, что вы каждый раз делите группу коммитов пополам, для обнаружения искомого вам потребуется примерно log(n) итераций (см. Сложность алгоритма).

Список команд, которые понадобятся вам для работы с git bisect:

  1. git bisect start — начинаем процедуры разделения
  2. git bisect good {{some-commit-hash}} — помечаем коммит как хороший (например, последний сделанный вами перед отпуском)
  3. git bisect bad {{some-commit-hash}} — помечаем плохой коммит (например, HEAD главной ветки, HEAD означает последний коммит)
  4. В этот момент Git находит срединный коммит и сообщает вам, что можно проводить проверку
  5. git bisect bad — сообщаем Git о том, что наша фича не работает в проверяемом в данный момент коммите
  6. git bisect good — сообщаем Git о том, что наша фича работает в проверяемом в данный момент коммите
  7. Когда первый плохой коммит будет найден, Git сообщит вам об этом, при этом выполнение git bisect завершается
  8. git bisect reset — возвращаемся начальной точке процесса git bisect (например, к HEAD главной ветки)
  9. git bisect log — отображает последний успешно выполненный git bisect

Данную процедуру можно автоматизировать с помощью скрипта.

Перевёл Dreadatour, текст читал %username%.

Коммиты, история коммитов и работа с файлами. Урок 4

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

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

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

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

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


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

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


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


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

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


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


    $ git add index.html
    $ git add css/main.css

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


    $ git add .

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


    $ git reset css/main.css

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


    $ git commit -m 'Added block students'

Флаг -m задает сообщение коммита (commit message). Оно нужно, чтобы описать изменения, которые делает этот коммит.
Подписывайте коммиты так, чтобы было понятно, что в нем происходит.

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


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


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


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


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


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

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

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

  • хэш (уникальный id), например, 239892a996…4784cf57f7
  • commit message (сообщение), например «Added block news»
  • список измененных файлов, например, index.html и css/main.css
  • изменения по каждому файлу, это то же самое, что показывает команда git diff из предыдущего урока
  • Как добавить файлы и сделать коммит одной командой

    
        $ git commit -a -m 'Commit message'
    

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

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


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


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

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


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

    
        $ git log
    


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

    
        $ git show hash_commit
    

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


    Если мы сделали коммит, но хотим поправить его commit message

    
        $ git commit --amend -m 'New commit message'
    


    Эта команда перезапишет сообщение последнего коммита. Это перезаписывание истории, операция опасная.
    Лучше делать ее только до того, как отправили коммит на сервер (push разберем через урок)


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

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


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

    
        $ git revert hash_commit
    


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

    
        $ git revert --no-edit hash_commit
    

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


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


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

    
        $ git add .
    


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


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

    
        $ git mv about.html company.html
    


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

    
        $ git rm about.html
    

    Командная строка 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 log


    Спасибо за внимание и до встречи!

    Все уроки курса

    Продолжение следует…

    Команда Git diff. Как сравнивать изменения в Git

    Сравнение с последним коммитом

    Для вывода изменений в файлах по сравнению с последним коммитом, используется git diff без параметров:

    git diff

    Команда выводит изменения в файлах, которые еще не были добавлены в индекс. Сравнение происходит с последним коммитом.

    Сравнение с последним коммитом, включая файлы в индексе

    Если вы изменили какие-нибудь файлы в вашем рабочем каталоге и добавили один или несколько из них в индекс (с помощью git add), то команда git diff не покажет изменения в этих файлах. Чтобы показать изменения в файлах, включая файлы, добавленные в индекс, используется ключ —cached:

    git diff --cached

    Сравнение коммитов

    Команда git diff позволяет сравнивать два различных коммита. Сначала нужно определить хеш (ID) коммитов, которые требуется сравнивать. Можно воспользоваться командой git log, чтобы вывести список коммитов и их идентификаторы:

    git log --oneline

    Теперь сравним два коммита. Для этого в качестве первого аргумента команде git diff указывается хеш первого коммита, а вторым аргументом хеш второго коммита, например:

    git diff 4612297 5e356cf

    Сравнение двух веток

    Для вывода всех изменений между концами двух веток, необходимо для git diff указать имена веток:

    git diff branch2 branch3

    Сравнение файлов между двумя ветками

    Чтобы сравнить конкретные файлы между двумя ветками используется команда:

    git diff branch2 branch3 ./myfile.cpp

    Вместо branch2, branch3 нужно указать название веток, а вместо myfile.cpp путь до сравниваемого файла. Через пробел можно добавить еще файлы для сравнения.

    Исключить некоторые файлы из сравнения

    Иногда нужно выполнить git diff, но исключить один или несколько файлов, чтобы команда git diff их проигнорировала. Для этого используется запись вида ’:(exclude)имя_файла’ или короткая запись ’:!имя_файла’

    Пример:

    git diff -- . ':(exclude)file1.abc' ':(exclude)file2.abc'

    Или более короткая запись:

    git diff -- . ':!file1.abc' ':!file2.abc'

    Сравнивать только изменения в файлах (игнорировать новые и удаленные файлы)

    Чтобы исключить из сравнения новые и удаленные файлы, можно воспользоваться опцией —diff-filter, которая позволяет выбирать какие именно изменения (файлы) нужно сравнивать.

    Чтобы выполнить сравнение только изменений внутри файлов (игнорируя новые, удаленные, переименованные файлы) используется ключ Modified (M) — —diff-filter=M:

    git diff --diff-filter=M

    Git на практике / Хабр

    Существует замечательная книга Pro Git, в которой подробно описаны все команды и возможности гита. Но после ее прочтения у многих остается непонимание того, как это все использовать на практике. В частности, у программистов разного уровня часто возникают вопросы о том, как работать с ветками в Git, когда их заводить и как мержить между собой. Порой мне попадались очень «оригинальные» и неоправданно усложненные схемы работы с гитом. В то время как в сообществе программистов уже сформировалась схема работы с гитом и ветками в нем. В этой статье я хочу дать краткий обзор основных моментов при работе с Git, и описать «классическую» схему работы с ветками. Многое из того что описано в этой статье будет справедливо и для других систем управления версиями.

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

    Для начала давайте разберемся с тем что такое ветка и коммит.

    Коммит

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

    У коммита есть и другие свойства. Например, дата коммита, автор, комментарий к коммиту и т.п.

    В качестве комментария обычно указывают те изменения, которые вносит этот коммит в код, или название задачи которую он решает.

    Git это распределенная система управления версиями. Это значит, что у каждого участника проекта есть своя копия репозитория, которая находиться в папке “.git”, которая расположена в корне проекта. Именно в этой папке хранятся все коммиты и другие объекты Git. Когда вы работаете с Git, он в свою очередь работает с этой папкой.

    Завести новый репозиторий очень просто, это делается командой

    git init

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

    git clone <url удаленного репозитория>

    После чего в текущей папке появляется директория .git в которой и будет содержаться копия удаленного репозитория.

    Существует несколько основных областей в которых находиться код.

    • Рабочая директория – это файлы в корне проекта, тот код с которым вы работаете.
    • Локальный репозиторий — она же директория “.git”. В ней хранятся коммиты и другие объекты.
    • Удаленный репозиторий – тот самый репозиторий который считается общим, в который вы можете передать свои коммиты из локального репозитория, что бы остальные программисты могли их увидеть. Удаленных репозиториев может быть несколько, но обычно он бывает один.
    • Есть еще одна область, с пониманием которой обычно бывают проблемы. Это так называемая область подготовленных изменений (staging area). Дело в том, что перед тем как включить какие-то изменения в коммит, нужно вначале отметить что именно вы хотите включить в этот коммит. В своей рабочей директории вы можете изменить несколько файлов, но в один конкретный коммит включать не все эти изменения.

    В целом работа с гитом выглядит так: вы меняете файлы в своей рабочей директории, затем добавляете эти изменения в staging area используя команду

    git add <имя/файла>

    При этом можно использовать маски со звездочкой.

    Потом вы делаете коммит в свой локальный репозиторий

    git commit –m “Комментарий к коммиту”

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

    git push

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

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

    git pull

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

    Код в рабочей области проекта образуется применением тех изменений, которые содержаться в коммитах. У каждого коммита есть свое имя, которое представляет собой результат хеш функции sha-1 от содержимого самого коммита.

    Просмотреть коммиты можно при помощи команды

    git log

    Формат ответа этой команды по дефолту не очень удобен. Вот такая команда выведет ответ в более читаемом виде

    git log --pretty=format:"%H [%cd]: %an - %s" --graph --date=format:%c

    Что бы закончить просмотр нужно нажать на клавишу q

    Посмотреть, что находиться в рабочей директории и staging area можно командой

    git status

    Рабочую директорию можно переключить на предыдущее состояние выполнив команду

    git checkout <hash коммита>

    Только перед тем как это делать выполните git status и убедитесь, что у вас нет никаких локальных и не зафиксированных изменений. Иначе Git не поймет, как ему переключаться. git status подскажет вам что можно сделать с локальными изменениями что бы можно было переключиться. Этого правила следует придерживаться и при всяких других переключениях рабочей области.

    Ветка

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

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

    git pull

    git checkout –b <имя новой ветки>

    Просто сделать ветку, не переключаясь на нее можно командой

    git branch <имя ветки>

    переключиться на ветку

    git checkout <имя ветки>

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

    Ветка обычно заканчивается специальным merge коммитом, который говорит, что ветку нужно объединить с какой-то другой веткой. В merge коммите содержатся две ссылки на два коммита которые объединяются в одну ветку.

    Существует другая ситуация при объединении веток, в которой merge может произойти без merge commit. Дело в том, что если в одной из веток не произошло никаких изменений, то необходимость в merge commit с двумя предками отпадает. В таком случае, при слиянии веток, Git просто сделает пометку о том, что дальше будут идти коммиты той ветки с которой эта ветка была объединена. Такая схема merge называется слияние-перемотка (fast-forward merge), визуально это можно представить вот так.

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

    Что бы смержить одну ветку в другую нужно вначале переключиться на ту ветку, в которую вы хотите смержить

    git checkout <имя ветки>

    Потом получить последние изменения сделанные в этой ветке выполнив

    git pull

    Затем выполнить команду

    git merge <имя ветки>

    Так выглядит работа с ветками в общих чертах.

    Обратите внимание на то, что перед тем как заводить новую ветку нужно выполнить git pull. Делается это по нескольким причинам.

    • Другой программист мог изменить код, в том числе внести такие изменения, которые повлияют на решение задачи, для которой вы заводите новую ветку. Эти изменения могут вам пригодиться при решении своей задачи.
    • Из-за этих изменений вы можете получить конфликт при мерже.
    • Больше шанс что у вас получится merge commit. Это не так плохо, как два предыдущих пункта. Но если можно избежать лишнего коммита, то почему бы этого не сделать?

    Популярные схемы работы с ветками в Git

    Теперь можно описать популярные схемы работы с ветками в гите.

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

    Классическая схема работы с ветками

    Обычно перед тем как взяться за решение какой-то задачи, программист заводит новую ветку от последнего рабочего коммита мастер ветки и решает задачу в этой новой ветке. В ходе решения он делает ряд коммитов, после этого тестирует код непосредственно в ветке задачи. А после того как задача решена, делают merge обратно в мастер ветку. Такую схему работы часто используют с юнит тестами и автоматизированным деплоем. Если юнит тесты будут покрывать весь код, то можно настроить деплой так, что вначале будут прогоняться все тесты в ветке задачи. А после этого, если они прошли успешно, будет происходить merge и деплой. При такой схеме можно добиться полной автоматизации при тестировании и деплои.

    Именная ветка

    Неопытные программисты заводят себе именную ветку и работают всегда в ней. Они решают по одной задачи за раз, и когда заканчивают решение одной из задач, делают новый Pull запрос через Web интерфейсе (об этом чуть ниже). Недостаток этого подхода в том, что так можно решать только одну задачу и нельзя быстро переключиться на решение другой задачи. Еще один недостаток в том, что ветки так со временем будут все сильнее расходиться и код в ветке программиста рано или поздно устареет относительно мастер ветки и его придется обновить. Для этого можно либо смержить мастер ветку в ветку программиста, либо завести новую ветку для этого программиста от последнего рабочего состояния в мастер ветке. Правда к тому времени, как это произойдет программист уже может освоить гит в достаточной мере что бы перейти на “классическую” схему работы. Таким образом эта схема имеет место быть для неопытных пользователей Git.

    Схема с dev веткой

    Другая схема очень похожа на классическую, только в ней помимо мастер ветки есть еще девелоперская ветка, которая деплоится на тестовый сервер. Такую ветку обычно называют dev. Схема работы при этом такая. Программист перед выполнением новой задачи заводит для нее ветку от последнего рабочего состояния в мастер ветке. Когда он заканчивает работу над задачей, то мержит ветку задачи в dev ветку самостоятельно. После этого, совместными усилиями задача тестируется на тестовом сервере вместе с остальными задачами. Если есть ошибки, то задачу дорабатывают в той же ветке и повторно мержат с dev веткой. Когда тестирование задачи заканчивается, то ВЕТКУ ЗАДАЧИ мержат с мастер веткой. Важно заметить, что в этой схеме работы с мастер веткой нужно мержить ветку задачи, а не dev ветку. Ведь в dev ветке будут содержаться изменения, сделанные не только в этой задаче, но и в других и не все эти изменения могут оказаться рабочими. Мастер ветка и dev ветка со временем будут расходиться, поэтому при такой схеме работы периодически заводят новую dev ветку от последнего рабочего состояния мастер ветки. Недостатком этого подхода является избыточность, по сравнению с классической схемой. Такую схему работы с ветками часто используют если в проекте нет автоматизированных тестов и все тестирование происходит вручную на сервере разработки.

    Так же следует отметить что эти схемы работы можно комбинировать между собой, если в этом есть какая-то необходимость.

    Pull запросы

    С этим понятием имеется путаница. Дело в том, что в Git есть две совершенно разные вещи, которые можно назвать Pull запросом. Одна из них, это консольная команда git pull. Другая это кнопка в web интерфейсе репозитория. На github.com она выглядит вот так

    Про эту кнопку и пойдет речь дальше.

    Если программист достаточно опытный и ответственный, то он обычно сам сливает свой код в мастер ветку. В противном случае программист делает так называемый Pull запрос. Pull запрос это по сути дела запрос на разрешение сделать merge. Pull запрос можно сделать из web интерфейса Git, или при помощи команды git request-pull. После того как Pull запрос создан, остальные участники могут увидеть это, просмотреть тот код который программист предлагает внести в проект, и либо одобрить этот код либо нет. Merge через pull запросы имеет свои плюсы и минусы. Минус в том, что для тесной команды опытных программистов такой подход будет лишним. Это будет только тормозить работу и вносить в нее оттенки бюрократии.

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

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

    Конфликты

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

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

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

    Делается это вот так

    git tag -a v1.0

    Что бы передать ветки в удаленный репозиторий нужно выполнить команду

    git push –tags

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

    git checkout <имя тега>

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

    Если вы будете придерживаться этих правил и “классической” схемы работы с ветками, то вам будет проще интегрировать ваш Git с другими системами. Например, с системой непрерывной интеграции или с репозиторием пакетов, таким как packagist.org. Обычно сторонние решения и всякие расширения рассчитаны именно на такую схему работы с гитом, и если вы сразу начнете делать все правильно, то это может стать большим плюсом для вас в дальнейшем.

    Это обзор основных моментов при работе с Git. Если вы хотите узнать про Git больше, то я вам посоветую прочитать книгу Pro Git. Вот здесь.

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

    Как изменить файлы в старом коммите (не последнем)

    Задача: внести изменения в файлы в старом коммите (не самом последнем/свежем).

  • Если вы уже изменили какие-либо файлы, то сначала нужно спрятать изменения. Для этого выполняем команду:
    git stash
  • Посмотрим список коммитов:
    git log --oneline
  • Выполняем команду git rebase -i и указываем ей коммит, который мы хотим изменить. В данном случае мы хотим изменить третий коммит (относительно HEAD).
    git rebase -i HEAD~3
  • Откроется текстовый редактор со списком коммитов. Измените слово pick на edit (или просто на букву e) у коммита, который вы хотите изменить.
  • Сохраните изменения в файле. Вы снова окажетесь в командной строке.
  • Теперь внесите те изменения, которые вы хотели сделать с файлами. Если вы на первом шаге спрятали эти изменения, то сейчас их можно снова извлечь:
    git stash pop

    Или же просто отредактируйте файлы.

  • Добавьте отредактированные файлы в индекс:
    git add myfile1 myfile2
  • Применим наши изменения к коммиту:
    git commit --amend --no-edit
  • Завершим процесс ребейза:
    git rebase --continue

    Если все пройдет успешно, то появится сообщение вида:

    Successfully rebased and updated refs/heads/master.
  • Как изменить несколько коммитов

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

    Выполняем последовательность действий, описанную выше, но на шаге 4 нужно указать несколько коммитов, которые вы хотите изменить. Для этого нужно изменить слово pick на edit сразу у нескольких коммитов в списке.

    После сохранения файла (шаг 5) вы переключитесь на первый коммит (который старее), который вы пометили для редактирования.

    Выполните для него шаги с 6 по 8. После этого вы переключитесь на следующий коммит, который вы пометили для редактирования. И так далее.

    Сравнение коммитов — GitHub Docs

    Документы GitHub

    • Все продукты

    • GitHub.com
      • Начиная

        • Быстрый старт

          • Настроить Git
          • Создать репо
          • Форк репо
          • Быть социальным
        • Изучение GitHub

          • Продукты GitHub
          • Изучение выпусков раннего доступа с предварительным просмотром функций
          • Типы аккаунтов GitHub
          • Часто задаваемые вопросы об изменениях в планах GitHub
          • GitHub CLI
          • GitHub Desktop
          • GitHub для мобильных устройств
          • Разрешения на доступ на GitHub
          • Глоссарий GitHub
          • Шпаргалка по Git

    .

    Git — Отмена изменений | Учебник Atlassian Git

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

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

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

    Поиск того, что потеряно: просмотр старых коммитов

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

      git log --oneline e2f9a78fe Заменено FlyControls на OrbitControls d35ce0178 Редактор: Панель ярлыков Поддержка Safari. Редактор 9dbe8d0cf: Боковая панель. Элементы управления для боковой панели. Настройки. Ярлыки. Убирайся. 05c5288fc Запрос на слияние # 12612 от TyLindberg / editor-controls-panel 0d8b6e74b Запрос на слияние # 12805 от harto / patch-1 23b20c22e Запрос на слияние # 12801 от gam0022 / Superior-raymarching-example-v2 fe78029f1 Исправить опечатку в документации 7ce43c448 Merge pull request # 12794 от WestLangley / dev-x 17452bb93 Merge pull request # 12778 от OndrejSpanel / unitTestFixes b5c1b5c70 Merge pull request # 12799 от dhritzkiv / patch-21 1b48ff4d2 Обновленные сборки.88adbcdf6 WebVRManager: очистить. 2720fbb08 Merge pull request # 12803 from dmarcos / parentPoseObject 9ed629301 Проверить родительский объект PoseObject вместо камеры 219f3eb13 Обновить GLTFLoader.js 15f13bb3c Обновить GLTFLoader.js 6d9c22a3b Обновить униформу только при изменении аспекта 900M Projection 900M в onWindow12Resize 881b25
     

    Каждая фиксация имеет уникальный хеш-идентификатор SHA-1. Эти идентификаторы используются для перемещения по зафиксированной временной шкале и повторного посещения коммитов. По умолчанию git log покажет только коммиты для выбранной в данный момент ветки.Вполне возможно, что коммит, который вы ищете, находится в другой ветке. Вы можете просмотреть все коммиты во всех ветках, выполнив команду git log --branches = * . Команда git branch используется для просмотра и посещения других веток. Вызов команды git branch -a вернет список всех известных имен веток. Затем одно из этих имен веток может быть зарегистрировано с помощью git log .

    Когда вы нашли ссылку фиксации на точку в истории, которую хотите посетить, вы можете использовать команду git checkout для посещения этого коммита. Git checkout - это простой способ «загрузить» любой из этих сохраненных снимков состояния на вашу машину разработки. Во время обычного процесса разработки HEAD обычно указывает на master или какую-либо другую локальную ветвь, но когда вы проверяете предыдущую фиксацию, HEAD больше не указывает на ветку - он указывает непосредственно на фиксацию. Это состояние называется «отсоединенным HEAD », и его можно визуализировать следующим образом:

    Извлечение старого файла не перемещает указатель HEAD .Он остается в той же ветке и той же фиксации, избегая состояния «отделенной головы». Затем вы можете зафиксировать старую версию файла в новом снимке, как и любые другие изменения. Таким образом, использование git checkout в файле, по сути, служит способом вернуться к старой версии отдельного файла. Для получения дополнительной информации об этих двух режимах посетите git checkout page

    Просмотр старой версии

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

      git журнал --oneline  

    Допустим, история вашего проекта выглядит примерно так:

      b7119f2 Продолжайте делать безумные вещи 872fa7e Попробуйте что-нибудь безумное a1e8fb5 Внесите некоторые важные изменения в hello.txt 435b61d Создайте hello.txt 9773e52 Первоначальный импорт  

    Вы можете использовать git checkout , чтобы просмотреть «Внести некоторые изменения импорта в hello.txt »следующим образом:

      git checkout a1e8fb5  

    Это заставляет ваш рабочий каталог соответствовать точному состоянию коммита a1e8fb5 . Вы можете просматривать файлы, компилировать проект, запускать тесты и даже редактировать файлы, не беспокоясь о потере текущего состояния проекта. Все, что вы здесь делаете, не будет сохранено в вашем репозитории. Чтобы продолжить разработку, вам необходимо вернуться в «текущее» состояние вашего проекта:

      git checkout master  

    Предполагается, что вы разрабатываете в ветке master по умолчанию.Вернувшись в ветку master , вы можете использовать либо git revert , либо git reset , чтобы отменить любые нежелательные изменения.

    Отмена зафиксированного снимка

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

      git log --oneline 872fa7e Попробуйте что-нибудь безумное a1e8fb5 Внесите важные изменения в hello.txt 435b61d Создайте hello.txt 9773e52 Начальный импорт  

    Мы сосредоточимся на отмена 872fa7e Попробуй что-нибудь безумное коммит .Может, все стало слишком сумасшедшим.

    Как отменить фиксацию с помощью git checkout

    Используя команду git checkout , мы можем проверить предыдущую фиксацию, a1e8fb5, , переводя репозиторий в состояние до того, как произошла сумасшедшая фиксация. Проверка конкретной фиксации переведет репо в состояние «отключенной HEAD». Это означает, что вы больше не работаете ни над какой веткой. В отсоединенном состоянии любые новые коммиты, которые вы делаете, будут потеряны, когда вы измените ветвь обратно на установленную ветку.Осиротевшие коммиты могут быть удалены сборщиком мусора Git. Сборщик мусора запускается с заданным интервалом и безвозвратно уничтожает потерянные коммиты. Чтобы предотвратить сбор мусора осиротевших коммитов, нам нужно убедиться, что мы находимся в ветке.

    Из состояния отсоединенной HEAD мы можем выполнить git checkout -b new_branch_without_crazy_commit . Это создаст новую ветку с именем new_branch_without_crazy_commit и переключится в это состояние. Репо теперь находится на новой временной шкале истории, в которой фиксация 872fa7e больше не существует.На этом этапе мы можем продолжить работу над этой новой веткой, в которой фиксация 872fa7e больше не существует, и считать ее «отмененной». К сожалению, если вам нужна предыдущая ветка, возможно, это была ваша master ветка , эта стратегия отмены не подходит. Давайте посмотрим на некоторые другие стратегии отмены. Для получения дополнительной информации и примеров просмотрите наше подробное обсуждение git checkout .

    Как отменить публичную фиксацию с помощью git revert

    Предположим, мы вернулись к нашему первоначальному примеру истории фиксации.История, которая включает фиксацию 872fa7e . На этот раз попробуем «отменить». Если мы выполним git revert HEAD , Git создаст новый коммит с инверсией последнего коммита. Это добавляет новую фиксацию в текущую историю веток, и теперь она выглядит так:

      git log --oneline e2f9a78 Отменить «Попробуйте что-нибудь безумное» 872fa7e Попробуйте что-нибудь безумное a1e8fb5 Внесите важные изменения в hello.txt 435b61d Создайте hello.txt 9773e52 Первоначальный импорт  

    На этом этапе мы снова технически «отменили» фиксацию 872fa7e .Хотя 872fa7e все еще существует в истории, новый коммит e2f9a78 является инверсией изменений в 872fa7e . В отличие от нашей предыдущей стратегии оформления заказа, мы можем продолжать использовать ту же ветку. Это решение - удовлетворительная отмена. Это идеальный метод «отмены» для работы с общедоступными общими репозиториями. Если у вас есть требования вести тщательно подобранную и минимальную историю Git, эта стратегия может быть неудовлетворительной.

    Как отменить фиксацию с помощью git reset

    Для этой стратегии отмены мы продолжим наш рабочий пример. git reset - обширная команда с множеством функций и применений. Если мы вызываем git reset --hard a1e8fb5 , история фиксации сбрасывается до указанной фиксации. Изучение истории фиксации с помощью git log теперь будет выглядеть так:

      git log --oneline a1e8fb5 Внесите важные изменения в hello.txt 435b61d Создайте hello.txt 9773e52 Первоначальный импорт  

    В выходных данных журнала отображается e2f9a78 и 872fa7e коммитов больше не существуют в истории коммитов.На этом этапе мы можем продолжить работу и создавать новые коммиты, как будто «сумасшедших» коммитов никогда не было. Этот метод отмены изменений имеет самое четкое влияние на историю. Сброс отлично подходит для локальных изменений, однако добавляет сложности при работе с общим удаленным репозиторием. Если у нас есть общий удаленный репозиторий, в который помещена фиксация 872fa7e , и мы пытаемся git push ветку, в которой мы сбросили историю, Git поймает это и выдаст ошибку.Git предполагает, что отправляемая ветка не обновлена ​​из-за отсутствия коммитов. В этих сценариях предпочтительным методом отмены должно быть git revert .

    Отмена последней фиксации

    В предыдущем разделе мы обсудили различные стратегии отмены коммитов. Все эти стратегии применимы и к самой последней фиксации. Однако в некоторых случаях вам может не понадобиться удалять или сбрасывать последнюю фиксацию. Может, это просто сделали преждевременно. В этом случае вы можете изменить самую последнюю фиксацию.После того, как вы внесли больше изменений в рабочий каталог и подготовили их для фиксации с помощью git add , вы можете выполнить git commit --amend . При этом Git откроет настроенный системный редактор и позволит вам изменить последнее сообщение фиксации. Новые изменения будут добавлены в исправленный коммит.

    Отмена незафиксированных изменений

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

    Рабочий каталог

    Рабочий каталог обычно синхронизируется с локальной файловой системой. Чтобы отменить изменения в рабочем каталоге, вы можете редактировать файлы, как обычно, используя свой любимый редактор. В Git есть несколько утилит, которые помогают управлять рабочим каталогом.Существует команда git clean , которая представляет собой удобную утилиту для отмены изменений в рабочем каталоге. Кроме того, git reset может быть вызван с параметрами --mixed или --hard и применит сброс к рабочему каталогу.

    Промежуточный индекс

    Команда git add используется для добавления изменений в промежуточный индекс. Git reset в основном используется для отмены изменений промежуточного индекса. Сброс --mixed переместит любые ожидающие изменения из промежуточного индекса обратно в рабочий каталог.

    Отмена публичных изменений

    При работе в команде с удаленными репозиториями необходимо уделять особое внимание отмене изменений. Git reset обычно следует рассматривать как «локальный» метод отмены. При отмене изменений в частной ветке следует использовать сброс. Это надежно изолирует удаление коммитов из других веток, которые могут использоваться другими разработчиками. Проблемы возникают, когда выполняется сброс в общей ветке, а затем эта ветка отправляется удаленно с помощью git push .Git заблокирует push в этом сценарии, жалуясь на то, что отправляемая ветка устарела из удаленной ветки, поскольку в ней отсутствуют коммиты.

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

    Сводка

    Мы рассмотрели много высокоуровневых стратегий для отмены действий в Git. Важно помнить, что в проекте Git есть несколько способов «отменить». Большая часть обсуждения на этой странице касалась более глубоких тем, которые более подробно объясняются на страницах, посвященных соответствующим командам Git. Наиболее часто используемые инструменты «отмены» - это git checkout, git revert и git reset . Вот некоторые ключевые моменты, которые следует запомнить:

    • После фиксации изменений они обычно становятся постоянными
    • Используйте git checkout для перемещения и просмотра истории фиксации
    • git revert - лучший инструмент для отмены общих общедоступных изменений
    • git reset лучше всего использовать для отмены локальных частных изменений

    Помимо основных команд отмены, мы рассмотрели другие утилиты Git: git log для поиска потерянных коммитов git clean для отмены незафиксированных изменений git add для изменения промежуточного индекса.

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

    .

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *