Получаем больше информации от git log


Оглавление (нажмите, чтобы открыть):

Получаем больше информации от git log

Команда git log может показать список коммитов. Сама по себе она показывает все коммиты достижимые из родительского коммита; но вы можете также сделать более определенный запрос:

Конечно вы можете комбинировать их; следующая команда найдет коммиты начиная с v2.5 которые затрагивают файл Makefile или любой файл в директории fs/:

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

Вы также можете попросить git log показать патчи:

Статистика в логах

Если вы передадите параметр —stat в ‘git log’, он покажет вам которые файлы изменились в этом коммите и как много строк кода было добавлено и удалено из каждого из них.

Форматирование вывода log

Вы можете форматировать вывод log так как это удобно. Параметр ‘—pretty’ может принимать множество предопределенных значений, таких как ‘oneline’ (в одну линию):

или вы можете получить ‘short’ (кратко) форматирование:

Далее список возможных вариантов ‘medium’, ‘full’, ‘fuller’, ’email’ или ‘raw’. Тут лучше поэкспериментировать, чтобы выяснить какой наиболее вам подходит. Если ни один из них не удовалетворяет вашим потребностям вы можете создать свой собственный формат задав параметр след.образом ‘—pretty=format’ (просмотрите документацию git log чтобы узнать все форматирующие параметры).

Другая интересная вещь которую вы можете сделать — это визуализировать граф коммитов ипользуя параметр ‘—graph’, след.образом:

Это даст вас очень легкое для восприятия ASCII представление истории коммитов.

Упорядочивание Log

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

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

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

Как бы там ни было, вы можете определить ‘—topo-order’, который выведет коммиты в хронологическом порядке (т.е. коммиты потомки будут выведены перед их родителями). Если мы просмотрим git log для репозитария Grit в —topo-order, то увидим что все линии разработки сгруппированы вместе.

Вы можете также использовать ‘—date-order’, который изначально упорядочивает коммиты по дате коммита. Этот параметр похож на —topo-order в том смысле что он располагает родителей позади потомков, но тем не менее вывод упорядочен по времени коммита. Вы можете видеть что линии разработки не сгруппированы здесь вместе, так что они скачут вокруг в процессе паралельной разработки:

В заключении, вы можете изменить порядок вывода на обратный используя параметр ‘—reverse’.

Git log ^ алгоритм

Я использую команду «git log ^», чтобы убедиться, что между двумя ветвями (скажем, текущим выпуском и предыдущим выпуском) в предыдущем выпуске нет коммита, который не является частью текущего выпуска (мы используем номер записи в сообщении фиксации, которое является базой для сравнения).

Мне было в основном интересно, каков алгоритм за командой. Кто-нибудь знает, как это работает?
Я полагаю, что вы можете получить все коммиты обеих веток и сравнить их один за другим. Однако, если история довольно длинная, это может быть длительным процессом.
Но я думаю, что есть более разумный способ сделать это. Идея состоит в том, чтобы найти общего предка, но не уверен, возможно ли это и как это можно сделать.

Если бы кто-то мог просветить меня, это было бы здорово 🙂

Из комментариев вы отметили, что:

Я действительно говорил о карете

.. Я должен был уточнить, что моей целью было бы сделать эту работу позже, используя Bitbucket API (вместо стандартных команд git) .

Это сделает вашу работу довольно сложной, если только часть используемого вами API не является git clone . 🙂 Точно, насколько сложно, зависит от того, можете ли вы получить информацию только о каждом коммит-объекте или вам нужен эквивалент git cherry .

Комментарий Кевина верен: то, что делает git log или git rev-list для реализации синтаксиса ^branch_exclude branch_include или branch_exclude..branch_include из gitrevisions , заключается в запуске поиска по ширине и / или глубине в графе фиксации. (Исходя из кода в revision.c , он в основном шириной.)

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

Внутри Git каждый коммит имеет свой хеш-идентификатор. Каждый коммит состоит из небольшого текстового объекта, который включает в себя родительские хеш-идентификаторы коммитов (по одному на каждого родителя). Эти две части, а также отправная точка, такая как идентификатор коммита HEAD или идентификатор из какого-либо имени ветви, — все, что нам нужно для простейшего вида обхода, то есть стандартного git rev-list графа git rev-list .

Обратите внимание, что большинство коммитов имеют только одного родителя: это обычные коммиты. По крайней мере, один коммит в графе не имеет родителей и является «корневым» коммитом. Самым первым коммитом, сделанным в репозитории, всегда является корневой коммит (вы можете получить больше корней с помощью git checkout —orphan или используя команды Git-plumbing). Некоторые коммиты являются слияниями : у них два или более родителей.

Простой график прогулок

Существует много алгоритмов обхода графа (см. Различные книги Седжвика, Ахо и, конечно, Кнута), но Git использует очень простой для начала: сохраняйте структуру данных в памяти ( struct commit ) для каждого коммита, с которым встречались до сих пор, и помечать объект, как только он «виден». Чтобы просмотреть график, учитывая некоторый хеш коммита H , мы помещаем H в очередь «коммитов для посещения». Тогда в не совсем-C:

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

Чтобы реализовать «коммиты, достижимые из идентификатора include но не из идентификатора exclude », мы могли бы использовать тот же алгоритм, но модифицированный: сначала мы обходим все коммиты, которые можно найти из exclude , устанавливая флаг SEEN, но ничего не печатая; затем мы помещаем хеш для include в очередь, снова идем и печатаем коммиты, которые мы посетили на этот раз, которые мы еще не посетили через исключение.

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

(Этот алгоритм является очень неоптимальным и, следовательно, не тем, что использует Git. Если вы прочитаете код, вы увидите, что специально исключенные коммиты фактически получают UNINTERESTING | BOTTOM , в то время как коммиты, исключенные посредством прогулок, получают набор UNINTERESTING . ) код в функции relevant_commit и его вызывающих программах, который помогает обрезать широкие полосы графика во время негативного обхода без необходимости проходить мимо них. Хитрость заключается в том, что мы должны знать, существует ли несколько способов достичь точки, которую мы бы хотели нравится обрезать прямо сейчас. Если нет, то можно пометить один коммит, который позволит избежать обхода его и всех его родителей во время позитивной прогулки.)

Git cherry

То, что git rev-list —cherry-mark git cherry (или git rev-list —cherry-mark , или любой другой подобный предмет), является более сложным, чем простые прогулки выше. Чтобы реализовать git cherry или его эквивалент, нам нужен не только граф коммитов, но и оставшиеся объекты в репозитории, потому что теперь мы хотим отметить коммиты, которые находятся «в» одном наборе, но не «в» другом наборе.

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

Теперь мы делаем один последний обход всех наших хранимых объектов коммитов (не по двум именам, а только над внутренними объектами struct commit ) и печатаем только коммиты «видно слева, но не справа», как левые коммиты, и печатаем только «увиденные справа, но не слева» фиксируют как правые коммиты. Это дает нам симметричную разницу.

Однако для реализации git cherry нам нужно пойти немного дальше. Для каждого коммита с одним родителем мы получаем набор изменений . (Обычно мы полностью игнорируем слияния, хотя можно превратить слияние в набор изменений для одного из его родителей.) Набор изменений в основном является результатом git diff

Теперь у нас есть сложная часть: каждый набор изменений может быть превращен в хеш-идентификатор, точно так же, как Git превращает все объекты Git-репозитория в хеш-идентификаторы. Если мы сделаем это осторожно, так, чтобы это не чувствительно к нумерации строк (и игнорировало сообщение о коммите, а также автора, дату и т. Д.), Мы получим то, что Git называет идентификатором патча .

Чтобы реализовать git cherry , мы помечаем все обычные коммиты на каждой «стороне» их идентификаторами патчей. Затем мы можем легко проверить при печати каждого коммита, есть ли каждый левый идентификатор патча в наборе всех правых идентификаторов патча, и наоборот. Это позволяет нам находить «отсутствующие» коммиты, даже если они были скопированы (через git cherry-pick или git rebase или аналогичные).

(Чтобы увидеть алгоритм, который Git фактически использует для симметричных различий, см. Источник. Флаг UNINTERESTING дополняется другим флагом, BOTTOM , и коммиты « UNINTERESTING » — те, где встречаются две стороны, что позволяет избежать некоторых родительских цепочек — помечаются с еще одним флагом, флагом BOUNDARY . Вы можете просмотреть эти коммиты, добавив —boundary к флагам, которые вы даете git rev-list . Я считаю, что —boundary не так полезен, как может показаться, потому что поиск в ширину сначала выполняется из несколько начальных точек могут иметь «лишние» границы, которые не понадобятся при поиске в других заказах.)

(Внутри флаг BOTTOM также используется для —ancestry-path вместе со списком «отрицательных ссылок», т. —ancestry-path Отрицание в ^X обозначает фиксацию, на которую X ссылается как на отрицательную ссылку, так и на «нижнюю» commit «, который затем попадает в этот список. Код обхода списка ревью может затем исключить коммит, который не имеет всех этих» нижних «коммитов как предков.)

Довольно git графы ветвей

1100 krosenvold [2009-06-29 13:12:00]

Я видел, что в некоторых книгах и статьях есть действительно красивые графические разделы ветвей и коммитов git. Как сделать высококачественные печатные изображения git истории?

git git-log directed-acyclic-graphs

31 ответ

Обновление: этот ответ получил гораздо больше внимания, чем он заслуживает. Это было изначально опубликовано, потому что я считаю, что графики выглядят красиво, и их можно было нарисовать в Illustrator для публикации, и лучшего решения не было. Но теперь есть гораздо более приемлемые ответы на этот вопрос, например fracz, Jubobs, или Гарри Ли! Пожалуйста, перейдите к ним!

Обновление 2: я опубликовал улучшенную версию этого ответа для Визуализации отраслевой топологии в git, так как это гораздо более уместно. Эта версия включает lg3 , которая показывает как автора, так и информацию коммиттера, поэтому вы действительно должны это проверить. Оставив этот ответ на исторические (и, я соглашусь, реплики) причины, хотя я действительно соблазн просто удалить его.

2 ¢: у меня есть два псевдонима, которые я обычно вбрасываю в мой файл

git lg / git lg1 выглядит следующим образом:

и git lg2 выглядит следующим образом:

738 Patoshi パトシ [2020-01-29 03:50:00]

Многие из ответов здесь хороши, но для тех, кто просто хочет получить ответ в одну строку без указания псевдонимов или чего-то еще, вот он:

Не все будут делать git log все время, но когда вам это нужно, просто помните:

«Собака»= мерзавец журнал — это LL — д ecorate — о neline — г Раф

303 keo [2009-06-30 01:25:00]

Для текстового вывода вы можете попробовать:

или: здесь псевдоним graphviz для рисования графика DAG.

Я лично использую gitx , gitk —all и gitnub .

194 fracz [2014-06-08 17:40:00]

Gitgraph.js позволяет рисовать красивые ветки git без репозитория. Просто напишите Javascript-код, который настраивает ваши ветки и фиксирует и отображает его в браузере.

или с шаблоном metro :

или с сообщениями, авторами и тегами фиксации:


Протестируйте его с помощью JSFiddle.

Сгенерируйте его с помощью Git Grapher от @bsara.

103 jubobs [2014-08-24 07:14:00]

Построено поверх TikZ и PGF, gitdags представляет собой небольшой пакет LaTeX, который позволяет вам без особых усилий создавать графики графической графики и т.д.

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

Я часто использую его для создания графиков для ответов на вопросы Git в качестве альтернативы графикам фиксации ASCII:

Вот пример такого графика, демонстрирующего эффекты простой перестановки:

Gitg — это клон Gitk и GitX для GNOME (он также работает на KDE и т.д.), который показывает довольно цветной график.

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

Он отлично работает с большими репозиториями и сложными графиками зависимостей.

Пример скриншотов, показывающих репозитории linux- git и linux-2.6:

57 太極者無極而生 [2012-09-17 03:52:00]

SourceTree — действительно хороший. Он распечатывает хорошо выглядящую и среднюю историю и график ветвей: (в экспериментальном проекте Git выполняется следующее, чтобы увидеть некоторые ветки). Поддерживает Windows 7+ и Mac OS X 10.6 +.

56 Harry Lee [2014-01-14 18:07:00]

Я только что написал один инструмент, который может генерировать симпатичный git фиксирует граф, используя HTML/Canvas.

И создайте плагин jQuery, который упростит его использование.

51 Tuxdude [2013-03-22 07:50:00]

git-forest — отличный perl script, который я использую больше года, и вряд ли использую git log команды напрямую.

Вот некоторые из вещей, которые мне нравятся в этом script:

  • Он использует символы Юникода для рисования линий на графике, что дает более постоянный вид линий графика.
  • Вы можете объединить —reverse с графическим выходом, что невозможно с помощью регулярной команды git log .
  • Он использует git log внутри, чтобы захватить список коммитов, поэтому все параметры, которые вы передаете на git log , также можно передать и на этот script.

У меня есть псевдоним, использующий git-forest следующим образом:

Вот как выглядит вывод на терминале:

Основываясь на скрипте Graphviz, который я нашел в ответе на связанный вопрос, я взломал скрипт ruby, который создает сводное представление хранилища git. Он исключает всю линейную историю и просто показывает «интересные» коммиты, то есть те, у которых несколько родителей, несколько детей или на которые указывает ветка или тег. Вот фрагмент графика, который он генерирует для jquery:

git-big-picture и BranchMaster — похожие инструменты, которые пытаются показать только высокоуровневую структуру графика, показывая только то, как связаны теги, ветки, слияния и т.д.

У этого вопроса есть еще несколько вариантов.

Я написал веб-инструмент для преобразования журналов git в красивые SVG-графики: Bit-Booster — инструмент для рисования графиков в автономном режиме

Загрузите вывод из git log —pretty=’%h|%p|%d’ прямо в инструмент, а затем нажмите ссылку «download graph.svg».

Этот инструмент предназначен исключительно для клиентской части, поэтому никакие ваши данные Git не передаются на мой сервер. Вы также можете сохранить HTML + JS локально и запустить его, используя URL «file:///». Проверено на Chrome 48 и Firefox 43 на Ubuntu 12.04.

Он генерирует HTML, который может быть размещен непосредственно на любой странице (включая движок блогов blogpot!). Посмотрите на некоторые сообщения в блоге здесь:

Вот скриншот образца HTML файла, сгенерированного инструментом:

36 Dustin [2009-06-29 18:37:00]

В зависимости от того, как они выглядели. Я использую gitx, который делает такие снимки:

Вы можете сравнить git log —graph vs. gitk с 24-way octopus merge (первоначально из https://clojure-log.n01se.net/date/2008-12-24.html):

34 gospes [2014-03-18 17:00:00]

Я добавил три команды: git tree , git stree и git vtree . Я пойду через них в таком порядке.

С git stree и git vtree я использую bash, чтобы помочь с форматированием.

EDIT: Это работает с git версией 1.9a. Значение цвета «auto», по-видимому, дебютирует в этом выпуске. Это приятное дополнение, потому что имена ветвей получат другой цвет. Это упрощает различие между локальными и удаленными ветвями, например.

30 kaoru [2011-06-02 11:52:00]

Для получения более подробного текстового вывода попробуйте:

Вы можете написать псевдоним в $HOME/.gitconfig

27 saeedgnu [2011-04-03 09:39:00]

gitg: просмотрщик репозитория на основе gtk, новый, но интересный и полезный https://git.gnome.org/browse/gitg
Я использую его в настоящее время

25 drzymala [2020-09-01 03:55:00]

Это мое мнение по этому вопросу:

Скриншот:

Использование:

git hist — Показать историю текущей ветки

git hist —all — Показать график всех ветвей (включая удаленные)

git hist master devel — Показать отношения между двумя или более ветвями

git hist —branches — Показать все локальные ветки

Добавить —topo-order сортировки —topo-order топологически, а не по дате (по умолчанию в этом псевдониме)

Выгоды:

  • Выглядит как обычный —decorate , поэтому с разными цветами для разных названий веток
  • Добавляет адрес коммитера
  • Добавляет фиксированную относительную и абсолютную дату
  • Сортирует совершает по дате

Настроить:

24 albfan [2014-04-05 03:32:00]

Хотя иногда я использую gitg, всегда возвращаюсь в командную строку:

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

  • — цвет: прозрачный внешний вид
  • — график: визуализировать родителей
  • — дата-порядок: наиболее понятный взгляд на репо
  • — украсить: кто есть кто
  • — oneline: много раз все, что вам нужно знать о фиксации
  • — упростить оформление: базовый для первого взгляда (только теги, соответствующие слияния, ветки)
  • — все: сохранение нажатий клавиш со всем псевдонимом с этой опцией и без нее.
  • — date = relative (% ar): понимать активность в репо (иногда ветка немного коммитируется рядом с мастером, но месяцев назад от него).

См. в последней версии git (1.8.5 и выше), вы можете использовать% C (auto) в украшении заполнителя% d

Отсюда вам нужно хорошо понять gitrevisions, чтобы фильтровать все, что вам нужно (что-то вроде master..develop, где -simplify-merges может помощь с длинными ветвями)

Сила за командной строкой — это быстрая конфигурация, основанная на ваших потребностях (понять, что репо не является уникальной конфигурацией журнала ключей, поэтому иногда требуется добавить -numstat или -raw или -name-status. Здесь git log и aliases бывают быстрыми, мощными и (со временем) самым красивым графиком, который вы можете достичь. Более того, с выходом, показанным по умолчанию через пейджер (скажем, меньше), вы всегда можете быстро искать результаты внутри. всегда может анализировать результат с помощью таких проектов, как gitgraph

Мастер Йода рекомендует:  Построение модуля Drupal 8 блоки и модули


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

Блог Makeomatic: разработка сайтов и мобильных приложений

Создавайте отчет о выполненной работе, используя Git Log

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

Способ создания git log

Результат можно достичь, в случае использования индивидуальных настроек:
git log —author=Vitaly # Поставьте свое имя

Генерируем следующий вывод данных:

Следующий шаг:

Ограничиваем лог последней неделей (или месяцем или…). Можем использовать его начиная и заканчивая следующими опциями:

git log —author=Vitaly —since=’1 sunday ago’ —until=’now’

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

git log —author=Vitaly —since=’2 sunday ago’ —until=’1 sunday ago’

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

%Cred%h%Creset %s %Cgreen(%ci) %Cblue %Creset

Демонстрируя commit hash %h , красный цвет %Cred , сообщение в коммите %s в стандартном цвете %Creset ,
время в коммите %ci , в зеленом цвете %Cgreen и имя автора %an , в голубом %Cblue и переключение цвета.
Большее кол-во вариантов форматирования вы можете посмотреть на официальном сайте

Создаем:

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

Генерируем:

У нас появился базовый отчет. Клиент не должен знать что это за соединение. На самом деле я предпочитаю удалять это сообщение, используя флаг no-merges :

Сейчас у нас есть полный отчет о проделанной работе.

На заметку:

Чтобы каждый раз не вписывать настройки, достаточно один раз их сохранить в git command .
Отредактируйте .git/config в своем репозитории и добавьте:

Теперь Вы можете:

получить отчет;
git report

создать больше отчетов;

Внимание: экранируйте “ в format используя \

CSV report создается:

git report-csv > report.csv

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

2. Основы работы с Git¶

Введение¶

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

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

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

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

Основы работы с удаленным репозиторием¶

git clone — создание копии (удаленного) репозитория¶

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

Клонируем репозиторий, используя протокол http:

Клонируем репозиторий с той же машины в директорию myrepo :

Клонируем репозиторий, используя безопасный протокол ssh:

У git имеется и собственный протокол:

Импортируем svn репозиторий, используя протокол http:

-s – понимать стандартные папки SVN (trunk, branches, tags)

git fetch и git pull — забираем изменения из центрального репозитория¶

Для синхронизации текущей ветки с репозиторием используются команды git fetch и git pull.

git fetch — забрать изменения удаленной ветки из репозитория по умолчания, основной ветки; той, которая была использована при клонировании репозитория. Изменения обновят удаленную ветку (remote tracking branch), после чего надо будет провести слияние с локальной ветку командой git merge.

git fetch /home/username/project — забрать изменения из определенного репозитория.

Возможно также использовать синонимы для адресов, создаваемые командой git remote :

git fetch username-project — забрать изменения по адресу, определяемому синонимом.

Естественно, что после оценки изменений, например, командой git diff , надо создать коммит слияния с основной:

Команда git pull сразу забирает изменения и проводит слияние с активной веткой.

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

Забрать изменения и метки из определенного репозитория:

Как правило, используется сразу команда git pull .

git push — вносим изменения в удаленный репозиторий¶

После проведения работы в экспериментальной ветке, слияния с основной, необходимо обновить удаленный репозиторий (удаленную ветку). Для этого используется команда git push.

Отправить свои изменения в удаленную ветку, созданную при клонировании по умолчанию:

Отправить изменения из ветки master в ветку experimental удаленного репозитория:

В удаленном репозитории origin удалить ветку experimental:

В удаленную ветку master репозитория origin (синоним репозитория по умолчанию) ветки локальной ветки master:

Отправить метки в удаленную ветку master репозитория origin:

Изменить указатель для удаленной ветки master репозитория origin (master будет такой же как и develop)

Добавить ветку test в удаленный репозиторий origin, указывающую на коммит ветки develop:

Работа с локальным репозиторием¶

Базовые команды¶

git init — создание репозитория

Команда git init создает в директории пустой репозиторий в виде директории .git , где и будет в дальнейшем храниться вся информация об истории коммитов, тегах — о ходе разработки проекта:


git add и git rm — индексация изменений

Следующее, что нужно знать — команда git add . Она позволяет внести в индекс — временное хранилище — изменения, которые затем войдут в коммит. Примеры использования:

индексация измененного файла, либо оповещение о создании нового:

внести в индекс все изменения, включая новые файлы:

Из индекса и дерева проекта одновременно файл можно удалить командой git rm :

хороший пример удаления из документации к git, удаляются сразу все файлы txt из папки:

внести в индекс все удаленные файлы:

Сбросить весь индекс или удалить из него изменения определенного файла можно
командой git reset :

сбросить весь индекс:

удалить из индекса конкретный файл:

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

git status — состояние проекта, измененные и не добавленные файлы, индексированные файлы

Команду git status , пожалуй, можно считать самой часто используемой наряду с
командами коммита и индексации. Она выводит информацию обо всех изменениях,
внесенных в дерево директорий проекта по сравнению с последним коммитом рабочей
ветки; отдельно выводятся внесенные в индекс и неиндексированные
файлы. Использовать ее крайне просто:

Кроме того, git status указывает на файлы с неразрешенными конфликтами слияния и
файлы, игнорируемые git.

git commit — совершение коммита

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

Если индекс не пустой, то на его основе будет совершен коммит, после чего
пользователя попросят прокомментировать вносимые изменения вызовом команды
edit . Сохраняемся, и вуаля! Коммит готов.

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

git reset — возврат к определенному коммиту, откат изменений, «жесткий» или «мягкий»

Помимо работы с индексом (см. выше), git reset позволяет сбросить состояние проекта до какого-либо коммита в истории. В git данное действие может быть двух видов: «мягкого»(soft reset) и «жесткого» (hard reset).

«Мягкий» (с ключом —soft ) резет оставит нетронутыми ваши индекс и все дерево файлов и директорий проекта, вернется к работе с указанным коммитом. Иными словами, если вы обнаруживаете ошибку в только что совершенном коммите или комментарии к нему, то легко можно исправить ситуацию:

  1. git commit — некорректный коммит
  2. git reset —soft HEAD^ — переходим к работе над уже совершенным коммитом, сохраняя все состояние проекта и проиндексированные файлы
  3. edit WRONGFILE
  4. edit ANOTHERWRONGFILE
  5. git add .
  6. git commit -c ORIG_HEAD — вернуться к последнему коммиту, будет предложено редактировать его сообщение. Если сообщение оставить прежним, то достаточно изменить регистр ключа -с:

Обратите внимание на обозначение HEAD^, оно означает «обратиться к предку последнего коммита». Подробней описан синтаксис такой относительной адресации будет ниже, в разделе «Хэши, тэги, относительная адресация». Соответственно, HEAD — ссылка на последний коммит. Ссылка ORIG_HEAD после «мягкого» резета указывает на оригинальный коммит.

Естественно, можно вернуться и на большую глубину коммитов,

«Жесткий» резет (ключ —hard ) — команда, которую следует использовать с
осторожностью. git reset —hard вернет дерево проекта и индекс в состояние,
соответствующее указанному коммиту, удалив изменения последующих коммитов:

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

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

git revert — отмена изменений, произведенных в прошлом отдельным коммитом

Возможна ситуация, в которой требуется отменить изменения, внесенные отдельным коммитом. git revert создает новый коммит, накладывающий обратные изменения.

Отменяем коммит, помеченный тегом:

Отменяем коммит, используя его хэш:

Для использования команды необходимо, чтобы состояние проекта не отличалось от состояния, зафиксированного последним коммитом.

git log — разнообразная информация о коммитах в целом

Иногда требуется получить информацию об истории коммитов; коммитах, изменивших
отдельный файл; коммитах за определенный отрезок времени и так далее. Для этих
целей используется команда git log .

Простейший пример использования, в котором приводится короткая справка по всем
коммитам, коснувшимся активной в настоящий момент ветки (о ветках и ветвлении
подробно узнать можно ниже, в разделе «Ветвления и слияния»):

Получить подробную информацию о каждом в виде патчей по файлам из коммитов
можно, добавив ключ -p (или -u):

Статистика изменения файлов, вроде числа измененных файлов, внесенных в них
строк, удаленных файлов вызывается ключом —stat :

За информацию по созданиям, переименованиям и правам доступа файлов отвечает ключ
—summary :

Чтобы просмотреть историю отдельного файла, достаточно указать в виде параметра
его имя (кстати, в моей старой версии git этот способ не срабатывает,
обязательно добавлять » — » перед «README»):

или, если версия git не совсем свежая:

Далее будет приводится только более современный вариант синтаксиса. Возможно
указывать время, начиная в определенного момента («weeks», «days», «hours», «s»
и так далее):

изменения, касающиеся отдельной папки:

Можно отталкиваться от тегов.

Все коммиты, начиная с тега v1:

Все коммиты, включающие изменения файла README, начиная с тега v1:

Все коммиты, включающие изменения файла README, начиная с тега v1 и заканчивая тегом v2:

Интересные возможности по формату вывода команды предоставляет ключ —pretty .

Вывести на каждый из коммитов по строчке, состоящей из хэша (здесь — уникального идентификатора каждого коммита, подробней — дальше):

Лаконичная информация о коммитах, приводятся только автор и комментарий:

Более полная информация о коммитах, с именем автора, комментарием, датой создания и внесения коммита:

В принципе, формат вывода можно определить самостоятельно:

Определение формата можно поискать в разделе по git log из Git Community Book
или справке. Красивый ASCII-граф коммитов выводится с использованием ключа
—graph .

git diff — отличия между деревьями проекта, коммитами и т.д.

Своего рода подмножеством команды git log можно считать команду git diff ,
определяющую изменения между объектами в проекте — деревьями (файлов и
директорий).

Показать изменения, не внесенные в индекс:

Изменения, внесенные в индекс:

Изменения в проекте по сравнению с последним коммитом:

Можно сравнивать «головы» веток:

или активную ветку с какой-либо:

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

Посмотреть изменения, внесенные любым коммитом в истории, можно командой git show :

git blame и git annotate — команды, помогающие отслеживать изменения файлов

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

Можно указать и конкретные строки для отображения:

Аналогично работает команда git annotate , выводящая и строки, и информацию о
коммитах, их коснувшихся:

git grep — поиск слов по проекту, состоянию проекта в прошлом

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


Поиск слова tst в проекте:

Подсчитать число упоминаний tst в проекте:

Поиск в старой версии проекта:

Команда позволяет использовать логическое И и ИЛИ.

Найти строки, где упоминаются и первое слово, и второе:

Найти строки, где встречается хотя бы одно из слов:

Ветвление¶

git branch — создание, перечисление и удаление веток

Работа с ветками — очень легкая процедура в git, все необходимые механизмы сконцентрированы в одной команде:

Просто перечислить существующие ветки, отметив активную:

Создать новую ветку new-branch:

Удалить ветку, если та была залита (merged) с разрешением возможных конфликтов в текущую:

Удалить ветку в любом случае:

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

git checkout — переключение между ветками, извлечение файлов

Команда git checkout позволяет переключаться между последними коммитами (если упрощенно) веток:

Создаст ветку, в которую и произойдет переключение

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

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

Вернуть файл (или просто вытащить из прошлого коммита) позволяет команда вида:

Вернуть somefile к состоянию последнего коммита:

Вернуть somefile к состоянию на два коммита назад по ветке:

git merge — слияние веток (разрешение возможных конфликтов)

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

Попробовать объединить текующую ветку и ветку new-feature:

В случае возникновения конфликтов коммита не происходит, а по проблемным файлам расставляются специальные метки а-ля svn; сами же файлы отмечаются в индексе как «не соединенные» (unmerged). До тех пор пока проблемы не будут решены, коммит совершить будет нельзя.

Например, конфликт возник в файле TROUBLE , что можно увидеть в git status .

Произошла неудачная попытка слияния:

Смотрим на проблемные места:

Индексируем наши изменения, тем самым снимая метки:

Совершаем коммит слияния:

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

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

git rebase — построение ровной линии коммитов

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

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

Предположим, имеется две ветки, master и topic, в каждой из которых было совершенно несколько коммитов начиная с момента ветвления. Команда git rebase берет коммиты из ветки topic и накладывает их на последний коммит ветки master.

Вариант, в котором явно указывается, что и куда накладывается:

на master накладывается активная в настоящий момент ветка:

После использования команды история становится линейной. При возникновении конфликтов при поочередном накладывании коммитов работа команды будет останавливаться, а в проблемные местах файлов появятся соответствующие метки. После редактирования — разрешения конфликтов — файлы следует внести в индекс командой git add и продолжить наложение следующих коммитов командой git rebase —continue . Альтернативными выходами будут команды git rebase —skip (пропустить наложение коммита и перейти к следующему) или git rebase —abort (отмена работы команды и всех внесенных изменений).

С ключом -i ( —interactive ) команда будет работать в интерактивном режиме. Пользователю будет предоставлена возможность определить порядок внесения изменений, автоматически будет вызывать редактор для разрешения конфликтов и так далее.

git cherry-pick — применение к дереву проекта изменений, внесенных отдельным коммитом

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

Изменения, внесенные указанным коммитом будут применены к дереву, автоматически проиндексированы и станут коммитом в активной ветке:

Ключ -n показывает, что изменения надо просто применить к дереву проекта без индексации и создания коммита

Прочие команды и необходимые возможности¶

Хэш — уникальная идентификация объектов

В git для идентификации любых объектов используется уникальный (то есть с огромной вероятностью уникальный) хэш из 40 символов, который определяется хэшируюшей функцией на основе содержимого объекта. Объекты — это все: коммиты, файлы, тэги, деревья. Поскольку хэш уникален для содержимого, например, файла, то и сравнивать такие файлы очень легко — достаточно просто сравнить две строки в сорок символов.

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

найти разницу текущего состояния проекта и коммита за номером… сами видите, каким:

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

Иногда хватает и четырех символов:

Читаем лог с коммита по коммит:

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

git tag — тэги как способ пометить уникальный коммит

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

Кроме этого в git представленные так называемые «легковесные тэги» (lightweight tags), состоящие только из имени и ссылки на коммит. Такие тэги, как правило, используются для упрощения навигации по дереву истории; создать их очень легко.

Создать «легковесный» тэг, связанный с последним коммитом; если тэг уже есть, то еще один создан не будет:

Пометить определенный коммит:

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

После создания тэга его имя можно использовать вместо хэша в любых командах вроде git diff , git log и так далее:

Обычные тэги имеет смысл использовать для приложения к коммиту какой-либо информации, вроде номера версии и комментария к нему. Иными словами, если в комментарии к коммиту пишешь «исправил такой-то баг», то в комментарии к тэгу по имени «v1.0» будет что-то вроде «стабильная версия, готовая к использованию».

Создать обычный тэг для последнего коммита; будет вызван текстовый редактор для составления комментария:

Создать обычный тэг, сразу указав в качестве аргумента комментарий:

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

Относительная адресация

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

Если после «птички» поставить цифру, то можно адресоваться по нескольким предкам коммитов слияния:


найти изменения по сравнению со вторым предком последнего коммита в master; HEAD здесь — указатель на последний коммит активной ветки:

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

что привнес «дедушка» нынешнего коммита:

Обозначения можно объединять, чтобы добраться до нужного коммита:

файл .gitignore — объясняем git, какие файлы следует игнорировать

Иногда по директориям проекта встречаются файлы, которые не хочется постоянно видеть в сводке git status . Например, вспомогательные файлы текстовых редакторов, временные файлы и прочий мусор.

Заставить git status игнорировать определенные файлы можно, создав в корне или глубже по дереву (если ограничения должны быть только в определенных директория) файл .gitignore . В этих файлах можно описывать шаблоны игнорируемых файлов определенного формата.

Пример содержимого такого файла:

Существуют и другие способы указания игнорируемых файлов, о которых можно узнать из справки git help gitignore .

Серверные команды репозитория¶

; git update-server-info : Команда создает вспомогательные файлы для dumb-сервера в $GIT_DIR/info и $GIT_OBJECT_DIRECTORY/info каталогах, чтобы помочь клиентам узнать, какие ссылки и пакеты есть на сервере.

Мастер Йода рекомендует:  Чему я научился, написав шесть функций, которые делали одно и то же

; git count-objects : Проверка, сколько объектов будет потеряно и объём освобождаемого места при перепаковке репозитория.
; git gc : Переупаковка локального репозитория.

Рецепты¶

Создание пустого репозитория на сервере

Импорт svn репозитория на Git-сервер

Git для начинающих. Часть 6. Просмотр информации по коммитам

Рассмотрим инструмент системы контроля версий git, который позволяет делать выборку и представлять пользователю коммиты, отправленные в репозиторий, в соответствии с заданными параметрами.

В прошлом уроке мы разобрались с тем, как фиксировать изменения в рабочей директории и отправлять коммиты в репозиторий. Рабочий процесс с использованием git, в упрощенном виде, выглядит следующим образом (пока не рассматриваем работу с удаленным репозиторием):

  1. Внесение изменений в рабочую директорию.
  2. Отправка изменений в stage .
  3. Формирование и отправка коммита на базе того, что лежит в stage , в репозиторий.

В процессе работы, в вашем репозитории накопится больше количество коммитов и довольно часто будет возникать необходимость их просматривать. Git предоставляет удобный способ просмотра информации по коммитам. Для демонстрации возможностей git , создадим репозиторий и добавим в него один файл – README.md , о том, как это сделать, можете прочитать в предыдущем уроке.

Для просмотра информации по сделанным вами (или вашими коллегами) коммитам используется команда git log .

Как видно из полученной информации, в репозиторий был отправлен один коммит с сообщением “[create repository]” , этот коммит сделал пользователь с именем Writer , его email: writer@somecompany.com , уникальный идентификатор коммита a98cce47b59256d00a853c421af4f7b9f0dc0a29 , и дата и время отправки коммита: 5 марта 2020 в 23:10:51 .

Внесем еще несколько изменений в наш репозитории. Добавим текст в файл README.md .

Зафиксируем эти изменения в репозитории.

Создадим файл main.c и добавим его в репозиторий.

Таким образом в нашем репозитории уже должно быть три коммита, проверим это.

Коммиты располагаются от новых к старым. Сделаем ещё несколько изменений.

Снова получим список всех коммитов.

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

В таком виде работать с коммитами уже намного удобнее. Если вы хотите просмотреть n последних коммитов, то укажите количество коммитов после ключа -n . Выведем три последних коммита.

Для вывода списка коммитов, начиная с какой-то временной метки, используйте ключ –since=” ” . Например, получим все коммиты, сделанные после 5-го марта 2020 года 23:21.

Для вывода списка коммитов до какой-то даты используется ключ –until . Получим с писок коммитов, сделанных до 5-го марта 2020 года 23:21.

Еще одним полезным ключом является –author , который позволяет вывести список коммитов, сделанных конкретным автором.

В приведенном выше примере, мы вывели все коммиты сделанные пользователем с именем Writer . Т.к. в нашем репозитории все коммиты сделаны от имени данного автора, то при любых других именах, передаваемых параметру –author , мы будем получать пустой список.

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

Теперь коммиты со словом add .

Для более продуктивного использования данной команды рекомендуем ознакомиться с возможностями утилиты grep . На этом мы закончим обзор команды git log .

Отличный курс по git делают ребята из GeekBrains , найдите в разделе “Курсы” курс “Git. Быстрый старт” , он бесплатный!

Получаем больше информации от git log

Получить подробную информацию о каждом коммите, отображая что изменилось

Вызвать статистику изменения файлов

Получить информацию по созданию, переименованию и изменению прав доступа y файлов

Исследовать историю отдельного файла

Вывести список коммитов папки etc, сделанных за последние 2 часа

Вывести список коммитов, сделанных в промежутке от 1 дня до 5 часов назад.

Вывести список коммитов, сделанных до 2 дней назад и после 1 дня назад

Просмотреть все коммиты, включающие изменения файла README, начиная с тега v1 и заканчивая тегом v2

Вывести на каждый из коммитов по строчке, состоящей из хэша (здесь — уникального идентификатора каждого коммита)

Вывести информацию о коммитах с указанием автора и комметария

Вывести информацию о коммитах с указанием имени автора, комментарием, датой создания и внесения коммита

Вывести ASCII-граф коммитов

Вывести информацию о коммитах с указанием имени автора, комментарием, датой создания и внесения коммита

Вывести номер коммита, имя автора и сообщение

Создать список изменений Changelog

Указываем временные промежутки при просмотре истории

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

Вывести список измененых файлов после каждого коммита

Вывести список измененых файлов после каждого коммита вместе с информацией о добавлении/изменении/удалении.

Вывести только первые несколько символов контрольной суммы SHA-1 вместо всех 40

Вывести время изменения коммитов в относительном формате (например, «2 недели назад») вместо использования полного формата

Показать коммиты, автор которых «Ivanov Sergei»

Git log, чтобы получить фиксацию только для определенной ветки

Я хочу перечислить все коммиты, которые являются только частью определенной ветки.

При следующем перечислении всех коммитов из ветки, а также из родительского (основного)

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

Я пытался использовать git for-each-ref , но он также перечисляет mybranch, поэтому на самом деле он исключает все:

Update:


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

Обновление (2013-02-13T15: 08):

Параметр -walk-reflogs хорош, но я проверил, что есть срок действия для логов (по умолчанию 90 дней, gc.reflogExpire).

Думаю, я нашел ответ, который я искал:

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

Похоже, что вы должны использовать cherry :

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

Как указывал VonC, вы ВСЕГДА сравниваете свою ветку с другой ветвью, так что узнайте свои ветки, а затем выберите, с кем сравнивать.

НО я хотел бы избежать необходимости знать имена других ветвей.

Я не думаю, что это возможно: ветвь в Git всегда основана на другой или, по крайней мере, на другой фиксации, как объясняется в git diff doesn ‘t достаточно показать:

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

— это просто указатели на определенные коммиты в DAG

Так что даже если git log master..mybranch — один ответ, он все равно будет показывать слишком много коммитов, если mybranch основан на myotherbranch , сам основан на master .

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

Наконец-то я нашел способ сделать то, что хотел OP. Это так же просто, как:

Команда отобразит все коммиты, которые достижимы из предоставленной ветки в формате графика. Но вы можете легко отфильтровать все фиксации на этой ветке, посмотрев на график коммитов, чей * — первый символ в строке фиксации.

Например, давайте рассмотрим выдержку git log —graph master в репозитории cakephp GitHub ниже:

Как вы можете видеть, только коммиты 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4 и c3f45e811e4b49fe27624b57c3eb8f4721a4323b имеют * , являющийся первым символом в строках фиксации. Эти коммиты взяты из ведущей ветки, а остальные четыре — из некоторых других ветвей.

Следующая команда оболочки должна делать то, что вы хотите:

Предостережения

Если вы выбрали mybranch , вышеуказанная команда не будет работать. Это потому, что фиксации на mybranch также достижимы на HEAD , поэтому Git не считает коммиты уникальными для mybranch . Чтобы заставить его работать, когда вычеркнуто mybranch , вы также должны добавить исключение для HEAD :

Однако вы не должны исключать HEAD , если не будет отмечен mybranch , иначе вы рискуете отображать коммиты, не относящиеся к mybranch .

Аналогично, если у вас есть удаленная ветвь с именем origin/mybranch , которая соответствует локальной ветке mybranch , вам нужно будет ее исключить:

И если удаленная ветка является ветвью по умолчанию для удаленного репозитория (обычно это значение только для origin/master ), вам также нужно будет исключить origin/HEAD :

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

Объяснение

Команда git rev-list представляет собой низкоуровневую (сантехническую) команду, которая выполняет указанные изменения и сбрасывает найденные идентификаторы SHA1. Подумайте об этом как эквивалент git log , за исключением того, что он показывает только сообщение журнала SHA1-no, имя автора, временную метку, ни один из этих «причудливых» материалов.

Параметр —no-walk , как следует из названия, предотвращает прохождение git rev-list от цепи родословной. Поэтому, если вы наберете git rev-list —no-walk mybranch , он будет печатать только один идентификатор SHA1: идентификатор фиксации наконечника ветки mybranch .

Аргументы —exclude=refs/heads/mybranch —all указывают git rev-list , чтобы начать с каждой ссылки, кроме refs/heads/mybranch .

Итак, когда вы запустите git rev-list —no-walk —exclude=refs/heads/mybranch —all , Git печатает идентификатор SHA1 фиксации наконечника для каждого рефвота, за исключением refs/heads/mybranch . Эти коммиты и их предки — это те коммиты, которые вас не интересуют — это те коммиты, которые вы не хотите видеть.

Другие коммиты — это те, которые вы хотите увидеть, поэтому мы собираем вывод git rev-list —no-walk —exclude=refs/heads/mybranch —all и рассказываем Git, чтобы показать все, кроме коммитов и их предков.

Аргумент —no-walk необходим для больших репозиториев (и это оптимизация для небольших репозиториев): без него Git придется печатать, и оболочке придется собирать (и хранить в памяти) еще много фиксации идентификаторов, чем это необходимо. С большим хранилищем количество собранных коммитов может легко превысить ограничение аргумента командной строки оболочки.

Git ошибка?

Я ожидал, что следующее будет работать:

но это не так. Я предполагаю, что это ошибка в Git, но, возможно, это намеренно.

2. Основы работы с Git¶

Введение¶

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

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

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

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

Основы работы с удаленным репозиторием¶

git clone — создание копии (удаленного) репозитория¶

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

Клонируем репозиторий, используя протокол http:

Клонируем репозиторий с той же машины в директорию myrepo :

Клонируем репозиторий, используя безопасный протокол ssh:

У git имеется и собственный протокол:

Импортируем svn репозиторий, используя протокол http:

-s – понимать стандартные папки SVN (trunk, branches, tags)

git fetch и git pull — забираем изменения из центрального репозитория¶

Для синхронизации текущей ветки с репозиторием используются команды git fetch и git pull.

git fetch — забрать изменения удаленной ветки из репозитория по умолчания, основной ветки; той, которая была использована при клонировании репозитория. Изменения обновят удаленную ветку (remote tracking branch), после чего надо будет провести слияние с локальной ветку командой git merge.

git fetch /home/username/project — забрать изменения из определенного репозитория.

Возможно также использовать синонимы для адресов, создаваемые командой git remote :

git fetch username-project — забрать изменения по адресу, определяемому синонимом.

Естественно, что после оценки изменений, например, командой git diff , надо создать коммит слияния с основной:

Команда git pull сразу забирает изменения и проводит слияние с активной веткой.

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

Забрать изменения и метки из определенного репозитория:

Как правило, используется сразу команда git pull .

git push — вносим изменения в удаленный репозиторий¶

После проведения работы в экспериментальной ветке, слияния с основной, необходимо обновить удаленный репозиторий (удаленную ветку). Для этого используется команда git push.

Отправить свои изменения в удаленную ветку, созданную при клонировании по умолчанию:

Отправить изменения из ветки master в ветку experimental удаленного репозитория:

В удаленном репозитории origin удалить ветку experimental:

В удаленную ветку master репозитория origin (синоним репозитория по умолчанию) ветки локальной ветки master:

Отправить метки в удаленную ветку master репозитория origin:


Изменить указатель для удаленной ветки master репозитория origin (master будет такой же как и develop)

Добавить ветку test в удаленный репозиторий origin, указывающую на коммит ветки develop:

Работа с локальным репозиторием¶

Базовые команды¶

git init — создание репозитория

Команда git init создает в директории пустой репозиторий в виде директории .git , где и будет в дальнейшем храниться вся информация об истории коммитов, тегах — о ходе разработки проекта:

git add и git rm — индексация изменений

Следующее, что нужно знать — команда git add . Она позволяет внести в индекс — временное хранилище — изменения, которые затем войдут в коммит. Примеры использования:

индексация измененного файла, либо оповещение о создании нового:

внести в индекс все изменения, включая новые файлы:

Из индекса и дерева проекта одновременно файл можно удалить командой git rm :

хороший пример удаления из документации к git, удаляются сразу все файлы txt из папки:

внести в индекс все удаленные файлы:

Сбросить весь индекс или удалить из него изменения определенного файла можно
командой git reset :

сбросить весь индекс:

удалить из индекса конкретный файл:

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

git status — состояние проекта, измененные и не добавленные файлы, индексированные файлы

Команду git status , пожалуй, можно считать самой часто используемой наряду с
командами коммита и индексации. Она выводит информацию обо всех изменениях,
внесенных в дерево директорий проекта по сравнению с последним коммитом рабочей
ветки; отдельно выводятся внесенные в индекс и неиндексированные
файлы. Использовать ее крайне просто:

Кроме того, git status указывает на файлы с неразрешенными конфликтами слияния и
файлы, игнорируемые git.

git commit — совершение коммита

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

Если индекс не пустой, то на его основе будет совершен коммит, после чего
пользователя попросят прокомментировать вносимые изменения вызовом команды
edit . Сохраняемся, и вуаля! Коммит готов.

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

git reset — возврат к определенному коммиту, откат изменений, «жесткий» или «мягкий»

Помимо работы с индексом (см. выше), git reset позволяет сбросить состояние проекта до какого-либо коммита в истории. В git данное действие может быть двух видов: «мягкого»(soft reset) и «жесткого» (hard reset).

«Мягкий» (с ключом —soft ) резет оставит нетронутыми ваши индекс и все дерево файлов и директорий проекта, вернется к работе с указанным коммитом. Иными словами, если вы обнаруживаете ошибку в только что совершенном коммите или комментарии к нему, то легко можно исправить ситуацию:

  1. git commit — некорректный коммит
  2. git reset —soft HEAD^ — переходим к работе над уже совершенным коммитом, сохраняя все состояние проекта и проиндексированные файлы
  3. edit WRONGFILE
  4. edit ANOTHERWRONGFILE
  5. git add .
  6. git commit -c ORIG_HEAD — вернуться к последнему коммиту, будет предложено редактировать его сообщение. Если сообщение оставить прежним, то достаточно изменить регистр ключа -с:

Обратите внимание на обозначение HEAD^, оно означает «обратиться к предку последнего коммита». Подробней описан синтаксис такой относительной адресации будет ниже, в разделе «Хэши, тэги, относительная адресация». Соответственно, HEAD — ссылка на последний коммит. Ссылка ORIG_HEAD после «мягкого» резета указывает на оригинальный коммит.

Естественно, можно вернуться и на большую глубину коммитов,

«Жесткий» резет (ключ —hard ) — команда, которую следует использовать с
осторожностью. git reset —hard вернет дерево проекта и индекс в состояние,
соответствующее указанному коммиту, удалив изменения последующих коммитов:

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

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

git revert — отмена изменений, произведенных в прошлом отдельным коммитом

Возможна ситуация, в которой требуется отменить изменения, внесенные отдельным коммитом. git revert создает новый коммит, накладывающий обратные изменения.

Отменяем коммит, помеченный тегом:

Отменяем коммит, используя его хэш:

Для использования команды необходимо, чтобы состояние проекта не отличалось от состояния, зафиксированного последним коммитом.

git log — разнообразная информация о коммитах в целом

Иногда требуется получить информацию об истории коммитов; коммитах, изменивших
отдельный файл; коммитах за определенный отрезок времени и так далее. Для этих
целей используется команда git log .

Простейший пример использования, в котором приводится короткая справка по всем
коммитам, коснувшимся активной в настоящий момент ветки (о ветках и ветвлении
подробно узнать можно ниже, в разделе «Ветвления и слияния»):

Получить подробную информацию о каждом в виде патчей по файлам из коммитов
можно, добавив ключ -p (или -u):

Статистика изменения файлов, вроде числа измененных файлов, внесенных в них
строк, удаленных файлов вызывается ключом —stat :

За информацию по созданиям, переименованиям и правам доступа файлов отвечает ключ
—summary :

Чтобы просмотреть историю отдельного файла, достаточно указать в виде параметра
его имя (кстати, в моей старой версии git этот способ не срабатывает,
обязательно добавлять » — » перед «README»):

или, если версия git не совсем свежая:

Далее будет приводится только более современный вариант синтаксиса. Возможно
указывать время, начиная в определенного момента («weeks», «days», «hours», «s»
и так далее):

изменения, касающиеся отдельной папки:

Можно отталкиваться от тегов.

Все коммиты, начиная с тега v1:

Все коммиты, включающие изменения файла README, начиная с тега v1:

Все коммиты, включающие изменения файла README, начиная с тега v1 и заканчивая тегом v2:

Интересные возможности по формату вывода команды предоставляет ключ —pretty .

Вывести на каждый из коммитов по строчке, состоящей из хэша (здесь — уникального идентификатора каждого коммита, подробней — дальше):

Лаконичная информация о коммитах, приводятся только автор и комментарий:

Более полная информация о коммитах, с именем автора, комментарием, датой создания и внесения коммита:

В принципе, формат вывода можно определить самостоятельно:

Определение формата можно поискать в разделе по git log из Git Community Book
или справке. Красивый ASCII-граф коммитов выводится с использованием ключа
—graph .

git diff — отличия между деревьями проекта, коммитами и т.д.

Своего рода подмножеством команды git log можно считать команду git diff ,
определяющую изменения между объектами в проекте — деревьями (файлов и
директорий).

Показать изменения, не внесенные в индекс:

Изменения, внесенные в индекс:

Изменения в проекте по сравнению с последним коммитом:

Можно сравнивать «головы» веток:

или активную ветку с какой-либо:

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

Посмотреть изменения, внесенные любым коммитом в истории, можно командой git show :


git blame и git annotate — команды, помогающие отслеживать изменения файлов

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

Можно указать и конкретные строки для отображения:

Аналогично работает команда git annotate , выводящая и строки, и информацию о
коммитах, их коснувшихся:

git grep — поиск слов по проекту, состоянию проекта в прошлом

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

Поиск слова tst в проекте:

Подсчитать число упоминаний tst в проекте:

Поиск в старой версии проекта:

Команда позволяет использовать логическое И и ИЛИ.

Найти строки, где упоминаются и первое слово, и второе:

Мастер Йода рекомендует:  Собеседование для программиста 5 вещей, о которых стоит знать

Найти строки, где встречается хотя бы одно из слов:

Ветвление¶

git branch — создание, перечисление и удаление веток

Работа с ветками — очень легкая процедура в git, все необходимые механизмы сконцентрированы в одной команде:

Просто перечислить существующие ветки, отметив активную:

Создать новую ветку new-branch:

Удалить ветку, если та была залита (merged) с разрешением возможных конфликтов в текущую:

Удалить ветку в любом случае:

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

git checkout — переключение между ветками, извлечение файлов

Команда git checkout позволяет переключаться между последними коммитами (если упрощенно) веток:

Создаст ветку, в которую и произойдет переключение

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

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

Вернуть файл (или просто вытащить из прошлого коммита) позволяет команда вида:

Вернуть somefile к состоянию последнего коммита:

Вернуть somefile к состоянию на два коммита назад по ветке:

git merge — слияние веток (разрешение возможных конфликтов)

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

Попробовать объединить текующую ветку и ветку new-feature:

В случае возникновения конфликтов коммита не происходит, а по проблемным файлам расставляются специальные метки а-ля svn; сами же файлы отмечаются в индексе как «не соединенные» (unmerged). До тех пор пока проблемы не будут решены, коммит совершить будет нельзя.

Например, конфликт возник в файле TROUBLE , что можно увидеть в git status .

Произошла неудачная попытка слияния:

Смотрим на проблемные места:

Индексируем наши изменения, тем самым снимая метки:

Совершаем коммит слияния:

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

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

git rebase — построение ровной линии коммитов

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

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

Предположим, имеется две ветки, master и topic, в каждой из которых было совершенно несколько коммитов начиная с момента ветвления. Команда git rebase берет коммиты из ветки topic и накладывает их на последний коммит ветки master.

Вариант, в котором явно указывается, что и куда накладывается:

на master накладывается активная в настоящий момент ветка:

После использования команды история становится линейной. При возникновении конфликтов при поочередном накладывании коммитов работа команды будет останавливаться, а в проблемные местах файлов появятся соответствующие метки. После редактирования — разрешения конфликтов — файлы следует внести в индекс командой git add и продолжить наложение следующих коммитов командой git rebase —continue . Альтернативными выходами будут команды git rebase —skip (пропустить наложение коммита и перейти к следующему) или git rebase —abort (отмена работы команды и всех внесенных изменений).

С ключом -i ( —interactive ) команда будет работать в интерактивном режиме. Пользователю будет предоставлена возможность определить порядок внесения изменений, автоматически будет вызывать редактор для разрешения конфликтов и так далее.

git cherry-pick — применение к дереву проекта изменений, внесенных отдельным коммитом

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

Изменения, внесенные указанным коммитом будут применены к дереву, автоматически проиндексированы и станут коммитом в активной ветке:

Ключ -n показывает, что изменения надо просто применить к дереву проекта без индексации и создания коммита

Прочие команды и необходимые возможности¶

Хэш — уникальная идентификация объектов

В git для идентификации любых объектов используется уникальный (то есть с огромной вероятностью уникальный) хэш из 40 символов, который определяется хэшируюшей функцией на основе содержимого объекта. Объекты — это все: коммиты, файлы, тэги, деревья. Поскольку хэш уникален для содержимого, например, файла, то и сравнивать такие файлы очень легко — достаточно просто сравнить две строки в сорок символов.

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

найти разницу текущего состояния проекта и коммита за номером… сами видите, каким:

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

Иногда хватает и четырех символов:

Читаем лог с коммита по коммит:

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

git tag — тэги как способ пометить уникальный коммит

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

Кроме этого в git представленные так называемые «легковесные тэги» (lightweight tags), состоящие только из имени и ссылки на коммит. Такие тэги, как правило, используются для упрощения навигации по дереву истории; создать их очень легко.

Создать «легковесный» тэг, связанный с последним коммитом; если тэг уже есть, то еще один создан не будет:

Пометить определенный коммит:

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

После создания тэга его имя можно использовать вместо хэша в любых командах вроде git diff , git log и так далее:

Обычные тэги имеет смысл использовать для приложения к коммиту какой-либо информации, вроде номера версии и комментария к нему. Иными словами, если в комментарии к коммиту пишешь «исправил такой-то баг», то в комментарии к тэгу по имени «v1.0» будет что-то вроде «стабильная версия, готовая к использованию».


Создать обычный тэг для последнего коммита; будет вызван текстовый редактор для составления комментария:

Создать обычный тэг, сразу указав в качестве аргумента комментарий:

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

Относительная адресация

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

Если после «птички» поставить цифру, то можно адресоваться по нескольким предкам коммитов слияния:

найти изменения по сравнению со вторым предком последнего коммита в master; HEAD здесь — указатель на последний коммит активной ветки:

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

что привнес «дедушка» нынешнего коммита:

Обозначения можно объединять, чтобы добраться до нужного коммита:

файл .gitignore — объясняем git, какие файлы следует игнорировать

Иногда по директориям проекта встречаются файлы, которые не хочется постоянно видеть в сводке git status . Например, вспомогательные файлы текстовых редакторов, временные файлы и прочий мусор.

Заставить git status игнорировать определенные файлы можно, создав в корне или глубже по дереву (если ограничения должны быть только в определенных директория) файл .gitignore . В этих файлах можно описывать шаблоны игнорируемых файлов определенного формата.

Пример содержимого такого файла:

Существуют и другие способы указания игнорируемых файлов, о которых можно узнать из справки git help gitignore .

Серверные команды репозитория¶

; git update-server-info : Команда создает вспомогательные файлы для dumb-сервера в $GIT_DIR/info и $GIT_OBJECT_DIRECTORY/info каталогах, чтобы помочь клиентам узнать, какие ссылки и пакеты есть на сервере.

; git count-objects : Проверка, сколько объектов будет потеряно и объём освобождаемого места при перепаковке репозитория.
; git gc : Переупаковка локального репозитория.

Рецепты¶

Создание пустого репозитория на сервере

Импорт svn репозитория на Git-сервер

Команды, важные в работе с Git

Git – это распределенная система контроля версий — каждый разработчик создает на своем компьютере отдельный, полноценный репозиторий. Git поддерживают несколько крупных репозиториев – GitHub, SourceForge, BitBucket — удобно использовать один из них в качестве основного хранилища для корпоративных проектов.
После создания удалённого репозитория для проекта на одном из вышеперечисленных сервисов (или ином соответствующим образом настроенном сервере), каждый разработчик должен получить свою локальную копию содержимого удалённого репозитория. Для этого:
1. Создаем на локальной машине новую директорию для проекта project_name, переходим в нее.
2. Выполняем следующую команду:

“./” в конце команды означает, что создать репозиторий нужно в текущей директории. Если не указать эти символы, внутри текущей папки будет создана директория c именем репозитория, в которой и будет находиться содержимое склонированного проекта.

Создание коммитов

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

Чтобы подготовить файлы к фиксации в коммите (говоря на языке Git — проиндексировать изменения), добавляем в него файлы командой:

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

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

Если над проектом работает кто-то помимо Вас, и он успел загрузить на сервер свои коммиты до Вас, то перед тем, как использовать команду git push, Вам необходимо использовать команду git pull, чтобы привести состояние вашего локального репозитория в соответствие с удалённым (иначе команда git push при выполнении выдаст ошибку).
В ходе этого процесса слияния Ваших локальных и удалённых данных могут возникнуть противоречия между ними (например, если Вы и Ваш коллега изменили одну и ту же часть одного и того же файла по-разному) — система git сама уведомит Вас, в каких файлах произошли неразрешимые для самой системы конфликты, и Вы сможете их надлежащим образом отредактировать.
Но что если конфликтный файл не подлежит редактированию — например, если он бинарный? Чтобы решить такой конфликт, надо просто выбрать – какая версия файла будет использоваться — ваша или из вливаемых данных. Чтобы использовать свой вариант файла, вводим команды:

Если мы выбираем версию из вливаемой ветки:

“ours” – от английского “наш”, “theirs” – от английского “их”.
Вышесказанное приводит нас к выводу — коммиты следует делать по возможности чаще, регулярно сверяясь с тем, как протекает работа у коллег — если коммиты будут содержать минимум изменений, локализовывать и устранять ошибки и конфликты придётся в меньшем количестве кода и файлов.

Просмотр изменений

git log — просмотр логов. Выводимый результат:

Вывод данных о каждом коммите в одну строку:

Поиск по ключевому слову в комментариях к коммиту:

Вывести сгруппированные по авторам коммиты:

Статистика изменения файлов, вроде числа измененных файлов, внесенных в них строк, удаленных файлов вызывается ключом —stat:

Команда git show позволяет просмотреть, какие именно изменения произошли в указанном коммите:

Чтобы увидеть, что же вы изменили, но пока не проиндексировали, наберите git diff (эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса):

Если вы хотите посмотреть, что вы проиндексировали и что войдёт в следующий коммит, вы можете выполнить git diff —staged (эта команда сравнивает ваши индексированные изменения с последним коммитом):

Также можно просмотреть разницу между любыми двумя коммитами (git diff commit1 commit2):

Показать, что за файлы менялись в коммите:

Ветки

Любой проект предусматривает множество контекстов, в которых ведётся работа; каждый компонент, исправление ошибки, эксперимент или альтернатива вашему продукту — это своего рода контекст сам по себе. Его можно рассматривать как отдельный «тематический раздел», чётко отграниченный от других таких разделов. Если такие тематические разделы не отделять друг от друга с помощью веток, неизбежно повышается риск появления проблем. Перемешивание тематических разделов в одном контексте:
1. Усложняет контроль над ними — а при большом количестве тематических разделов он становится почти невозможным;
2. Усложняет откат какого-либо действия, которое привело к ошибке, так как оно уже смешалось со слишком большим количеством других вещей;
3. Не вдохновляет людей на эксперименты, так как после смешивания экспериментального кода с основным кодом проекта становится очень трудно извлечь его из репозитория.
Чтобы создать новую ветку на основании текущего состояния, нужно выбрать имя и выполнить одну команду в командной строке. Допустим, мы хотим начать работу над новой версией контактной формы, следовательно создадим новую ветку под названием «contact-form»:

Если выполнить команду git branch не указывая имя ветки, мы получим список всех веток, которые есть на локальном репозитории (а ключ -v предоставит немного дополнительной информации):

Маленькая звёздочка напротив ветки под названием «master» обозначает ветку, которая на данный момент является активной. Итак, перед тем, как начать работу над нашей контактной формой, нужно сделать её активным контекстом:

Теперь эта ветка — наш текущий рабочий контекст (на языке Git это называется «HEAD branch»). Все изменения и любой коммит, совершённые с текущего момента, будут влиять только на этот контекст — остальные контексты останутся нетронутыми. Чтобы переключить контекст на другую ветку, мы просто снова используем команду git checkout.
Чтобы добавить изменения из одной ветки в другую, можно выполнить их «слияние» в текущий рабочий контекст. Например, если мы некоторое время работали над нашим компонентом «contact-form», а теперь желаем добавить эти изменения в ветку «master», то нам нужно переключиться на эту ветку и выполнить git merge:

Полезная возможность для выяснения состояния веток состоит в том, чтобы составить список только тех веток, которые Вы слили (или не слили) в текущую ветку. Для этих целей в Git’е есть опции —merged и —no-merged. Чтобы посмотреть те ветки, которые Вы уже слили с текущей, выполните команду git branch —merged:

Вывод всех локальных и удалённых веток:

Получить имя текущей ветки:

Переименовать текущую ветку:

Одну конкретную ветку можно склонировать из удалённого репозитория:

«Черновики» изменений

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

Тепеь Ваш рабочий каталог чист:

В данный момент Вы легко можете переключить ветки и поработать где-то ещё — ваши изменения сохранены в стеке. Чтобы посмотреть, что у Вас есть припрятанного, выполните git stash list:

В нашем случае две «заначки» были сделаны ранее, так что у вас теперь три разных припрятанных работы. Вы можете снова применить ту, которую только что спрятали, с помощью команды, показанной в справке в выводе первоначальной команды stash: git stash apply. Если вы хотите применить одну из старых заначек, можете сделать это, указав её имя так: git stash apply [email protected] . Если не указывать конкретный стек, Git будет подразумевать, что вы хотите применить последнюю спрятанную работу:

Как видите, Git восстановил изменения в файлах, которые былиы отменены командой stash. В нашем случае у Вас был чистый рабочий каталог, когда вы восстанавливали спрятанные изменения, и к тому же вы делали это на той же ветке, на которой находились во время прятанья. Но наличие чистого рабочего каталога и применение на той же ветке не обязательны для git stash apply. Вы можете спрятать изменения на одной ветке, переключиться позже на другую ветку и попытаться восстановить изменения. У вас в рабочем каталоге также могут быть изменённые и недокоммиченные файлы во время применения спрятанного — Git выдаст вам конфликты слияния, если что-то уже не может быть применено чисто.
Изменения в файлах были восстановлены, но проиндексированные файлы — нет. Чтобы воостановить и их, выполнить команду git stash apply с опцией —index.
Всё, что делает опция apply — это пытается применить спрятанную работу — то, что вы спрятали, всё ещё будет находиться в стеке. Чтобы удалить спрятанное, выполните git stash drop с именем «заначки», которую нужно удалить:

Также можно выполнить git stash pop, чтобы применить спрятанные изменения и сразу же удалить их из стека, а просто для удаления всех «черновиков» — git stash clear.
При некоторых сценариях использования, может понадобиться применить спрятанные изменения, поработать, а потом отменить изменения, внесённые командой stash apply — это делается так:

Опять же, если не указывать параметр для stash, Git подразумевает то, что было спрятано последним:

Исправление изменений

Очень легко забыть указать какое-либо изменение или допустить опечатку в комментарии к коммиту. С помощью ключа —amend к команде git commit Git даёт вам возможность изменить самый последний коммит — например, если вы забыли добавить какое-либо изменение и допустили опечатку в названии коммита, это можно легко исправить:

Помните: коммит, который уже был отослан в удалённый репозиторий, изменять нельзя!
Изменения, для которых не был совершён коммит, называются «локальными». Сброс этих изменений может потребоваться, когда текущий результат вашей работы оказался… скажем, хуже чем то, что было раньше. В Git можно отменить локальные изменения и начать сначала с последней версии вашего проекта, для которой был совершён коммит.
Если вы хотите восстановить один файл, можете использовать команду git checkout (команда нам уже знакома, но в текущем случае она выполняет иные функции):

Если день совсем не задался, и требуется сбросить все локальные изменения и восстановить весь проект целиком, то делаем так (это заменит все файлы в вашей рабочей директории на последнюю редакцию, для которой был совершён коммит):

Будьте осторожны с этими операциями: поскольку локальные изменения не были зарегистрированы в репозитории, после сброса восстановить их будет невозможно!
Отменить можно не только локальные изменения, но и некоторые коммиты, когда это необходимо — например, если они привели к ошибке в коде.
Команда git reset позволяет буквально вернуться в прошлое — Вы сообщаете к какой версии вы хотите вернуться, и она восстанавливает именно это состояние — отменяя все изменения, которые были осуществлены после этой временной точки. Нужно указать ей коммит, к которому вы хотите вернуться:

Чтобы восстановить просто самый свежий коммит:

Опция -—hard — это наиболее простой и чистый способ, однако она также удаляет все локальные изменения в вашей рабочей директории. Так что перед её применением, убедитесь, что у Вас нет локальных изменений, которые лучше было бы сохранить.
Команда git revert используется в другой ситуации. Представьте, что у Вас есть коммит, от которого Вы бы хотели избавиться, однако коммиты, совершённые после него, все ещё актуальны. В таком случае нельзя использовать команду git reset, потому что она отменит и эти, более поздние коммиты.
Команда revert позволяет откатить последствия от одного конкретного коммита. Она не удаляет какие-либо коммиты, в отличие от git reset — вместо этого она вносит изменения, противоположные изменениям в коммите, который подлежит откату. Например, если вы удалили строку кода, revert добавит точно такую же строку.
Чтобы откатить коммит 2be18d9:

Чтобы откатить самый свежий коммит:

Поиск ошибок

Часто возникает ситуация вида — Вы уверены, что два дня назад всё работало, а теперь — не работает — например, мы знаем, что текущая версия (с меткой «2.0») приведена в негодность, также мы знаем, что несколько коммитов назад (в версии «1.9»), всё было нормально.
Этой информации уже достаточно, чтобы начать охоту на ошибки с помощью git bisect:

После начала процесса мы сообщили Git, что наш текущий коммит содержит ошибку и обозначили его как «плохой» («bad»). Затем мы сообщили Git какой из предыдущих коммитов точно был рабочим (в качестве параметра для команды git bisect good).
Git после этого восстанавливает проект посередине между заведомо хорошим и плохим состоянием:

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

Таким образом Вы очень быстро определите, где именно была допущена ошибка. Когда это произойдёт, выполните git bisect reset, чтобы закончить охоту за ошибкой и восстановить исходное состояние проекта.

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