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

Git reflog что это

  • автор:

Git, я хочу все отменить! Команды исправления допущенных ошибок

image

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

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

Черт, я сделал что-то не то. Дайте мне волшебную машину времени!

git reflog # you will see a list of every thing you've # done in git, across all branches! # each one has an index HEAD@ # find the one before you broke everything git reset HEAD@ # magic time machine

image

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

Я сделал коммит, но сразу же заметил ошибку, ее нужно исправить!

# make your change git add . # or add individual files git commit --amend --no-edit # now your last commit contains that change! # WARNING: never amend public commits

Команда дает возможность поправить неприятные мелочи — когда вы что-то закоммитили, а потом увидели проблему вроде отсутствующего пробела после знака » plaintext»>git commit —amend # follow prompts to change the commit message

Это просто… глупые требования к оформлению сообщений.

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

# create a new branch from the current state of master git branch some-new-branch-name # remove the last commit from the master branch git reset HEAD~ --hard git checkout some-new-branch-name # your commit lives in this branch now :)

Если вы уже закоммитили в публичную ветку, команды не сработают. В этом случае поможет git reset HEAD@ вместо HEAD~.

Ну вот, я ошибочно закоммитил не в ту ветку

# undo the last commit, but leave the changes available git reset HEAD~ --soft git stash # move to the correct branch git checkout name-of-the-correct-branch git stash pop git add . # or add individual files git commit -m "your message here"; # now your changes are on the correct branch

Есть еще один способ, который использует большое количество разработчиков — это cherry-pick.

git checkout name-of-the-correct-branch # grab the last commit to master git cherry-pick master # delete it from master git checkout master git reset HEAD~ --hard

Мне нужно запустить diff, но ничего не получается

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

git diff —staged

В общем, это не баг, а фича, но она чертовски неочевидная ¯\_(ツ)_/¯

Мне срочно нужно отменить коммит, который сделан 5 коммитов назад

# find the commit you need to undo git log # use the arrow keys to scroll up and down in history # once you've found your commit, save the hash git revert [saved hash] # git will create a new commit that undoes that commit # follow prompts to edit the commit message # or just save and commit

К счастью, не нужно отказываться назад на 5 коммитов, занимаясь копипастом старых и новых файлов. Отменить все это можно при помощи revert.

Кроме того, откатить можно не только коммит, но и целый файл. Правда, это уже будут другие команды…

Отменить изменения в файле

А вот и они, эти другие команды.

# find a hash for a commit before the file was changed git log # use the arrow keys to scroll up and down in history # once you've found your commit, save the hash git checkout [saved hash] -- path/to/file # the old version of the file will be in your index git commit -m "Wow, you don't have to copy-paste to undo"

Когда я впервые нашел эту возможность, это было КРУТО, КРУТО, К-Р-У-Т-О. Но если задуматься — почему именно checkout — лучший вариант для отмены изменений в файле? :shakes-fist-at-linus-torvalds:

Все, я сдаюсь

cd .. sudo rm -r fucking-git-repo-dir git clone https://some.github.url/fucking-git-repo-dir.git cd fucking-git-repo-dir

Спасибо Eric V. За этот способ. И все жалобы по поводу использования sudo адресуйте ему.

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

# get the lastest state of origin git fetch origin git checkout master git reset --hard origin/master # delete untracked files and directories git clean -d --force # repeat checkout/reset/clean for each borked branch

Внимание! Эта статья не является исчерпывающим руководством. И да, есть и другие способы сделать то же самое, причем еще лучше. Но я пришел именно к этим вариантам методом проб и ошибок. Потом у меня появилась сумасшедшая идея поделиться находками. Берите это или уходите!

image

Комментарий эксперта

Даниил Пилипенко, директор центра подбора IT-специалистов SymbioWay и евангелист бэкенд-направления онлайн-университета Skillbox, дополнил перевод мнением о Git и его актуальности для разработчиков.

Git появился в 2005-ом году, и он далеко не сразу занял рынок. Помню, когда мы ещё в 2008-ом году в команде разработчиков внедряли SVN. И даже в 2012-ом одна близкая ко мне компания усиленно внедряла Mercurial. С годами для многих стало очевидным, что Git — это лучшая система контроля версий, и её теперь используют практически все разработчики.

Если вы начинающий разработчик и собираетесь устраиваться на работу, обязательно изучите Git! Вы должны знать, что такое система контроля версий и зачем она нужна, что такое коммит, ветка, как клонировать репозиторий и отправлять сделанные изменения на сервер, как получать новые изменения с сервера, как делать merge, какие бывают виды “reset”. Поначалу эта тема вам может показаться непонятной и сложной, но вам нужно лишь привыкнуть пользоваться Git, и отвыкнуть вы уже не сможете.

  • Блог компании Skillbox
  • Программирование
  • Git
  • Лайфхаки для гиков

Git: Руководство по исправлению ошибок (Часть 2)

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

  • Git: Руководство по исправлению ошибок (Часть 1)
  • Git: Руководство по исправлению ошибок (Часть 2)

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

Восстановление удалённой ветви с помощью Reflog

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

К счастью, есть способ вернуть эту ветвь из мёртвых — с помощью инструмента Git под названием Reflog. Мы использовали этот инструмент в первой части, но немного напомню: reflog похож на журнал, в котором Git отмечает каждое движение HEAD в вашем локальном репозитории. Другими словами: каждый раз когда вы выполняете checkout , commit , merge или rebase создаётся запись в журнале. Это делает reflog идеальной подстраховкой, если что-то пошло нет!

Рассмотрим конкретный пример.

$ git branch 
* feature/login
master

Мы видим, что в настоящее время мы переключены на ветку feature/login . Допустим, это ветвь, которую мы собираемся удалить (случайно). Однако, прежде чем мы сможем это сделать, нам нужно переключиться на другую ветвь. Потому что мы не можем удалить ветвь на которую указывает HEAD .

git checkout master 
git branch -d feature/login

Наша ветвь feature/login исчезла — я дам вам минуту, что бы (а) понять серьёзность нашей ошибки и (б) немного всплакнуть. После того как вы вытерли слёзы, нам нужно найти способ вернуть эту ветвь! Давайте откроем Reflog (просто набрав git reflog ) и посмотрим, что он нам приготовил:

git reflog

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

  • Прежде всего, вам нужно знать, что Reflog сортирует свои записи в хронологическом порядке: самые новые находятся в верхней части списка.
  • Самый верхний (и, следовательно, самый новый) элемент — это команда git checkout , которую мы выполнили перед удалением ветви. Она записана здесь в Reflog, потому что это одно из «перемещений указателя HEAD», которые Reflog так старательно фиксирует.
  • Чтобы исправить нашу серьёзную ошибку, мы можем просто вернутся в предыдущее состояние, которое также чётко и ясно записано в Reflog!

Итак, давайте попробуем вернуть это состояние, создав новую ветвь (с именем нашей «потерянной» ветви), которое было «до» с хэшем SHA-1:

git branch feature/login 776f8ca

И вуаля! Вы будете счастливы, увидев, что мы восстановили, казалось бы, потерянную ветвь!

Если вы используете приложения для Git, такие, как Tower, вы можете воспользоваться сочетанием клавиш Ctrl + Z на клавиатуре, для отмены последней команды — даже если вы только что жестоко удалили ветвь репозитория!

Перенос коммита в другую ветвь

Во многих командах существует договорённость не делать коммитов в долгосрочные ветви, такие как main и develop : такие ветви должны получать новые коммиты только через интеграцию ( merge или rebase ). И всё же, конечно, ошибки неизбежны: мы иногда забываем и делаем коммиты в эти ветви! Итак, как мы можем навести порядок в созданном нами беспорядке?

Ошибочный коммит

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

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

git checkout feature/login 
git cherry-pick 776f8caf

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

Но, осталось сделать ещё одно дело: нам нужно очистить ветвь, в которую он случайно попал в начале! Команда cherry-pick создала копию коммита, но оригинал всё ещё присутствует в долгосрочной ветви:

git cherry-pick

Это означает, что мы должны вернутся к нашей долгосрочной ветви и использовать git reset для удаления коммита:

git checkout main 
git reset --hard HEAD~1

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

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

Редактирование сообщения старого коммита

Слишком легко пропустить опечатку в сообщении коммита — и обнаружить её намного позже. В таком случае старую добрую опцию git —amend нельзя использовать для решения проблемы, потому что она работает только для самого последнего коммита. Чтобы исправить более ранний коммит, мы должны прибегнуть к инструменту Git под названием «Интерактивное Перебазирования».

Список коммитов

Во-первых, мы должны сообщать «Interactive Rebase», какую часть истории коммитов хотим редактировать. Это делается путём передачи хэша коммита: родительского коммита, предка того коммита которым хотим манипулировать.

git rebase -i 6bcf266b

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

Interactive Rebase

Здесь важно, чтобы вы не последовали своему первому импульсу: на этом этапе мы ещё не редактируем сообщение коммита. Вместо этого мы только сообщаем Git, какие манипуляции хотим сделать и с какими коммитами. Очень удобно, что в комментариях внизу окна есть список ключевых слов для действий. В нашем случае мы помечаем строку №1 reword (тем самым заменяя стандартную pick )

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

Вот вам краткий обзор всего процесса:

Исправление сломанного коммита (очень элегантным способом)

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

  1. Возможно, вы забыли добавить файл, должны были что-то удалить, внесли неправильную правку или просто опечатку. fixup работает во всех этих ситуациях.
  2. Наша нормальная инстинктивная реакция на ошибку в коммите — создание нового коммита для устранения проблемы. Такой способ, каким бы интуитивным он не казался, скоро сделает вашу историю коммитов хаотичной. У вас есть «оригинальные» коммиты, а затем эти небольшие «заплатки», которые исправляют то, что пошло не так в исходных коммитах. Ваша история усеяна небольшими бессмысленными коммитами, из-за которых сложно понять, что произошло в вашей кодовой базе.

Сломанные коммиты

Вот тут-то и пригодится fixup . Он позволяет вам по-прежнему делать эти исправляющие коммиты. Но здесь начинается волшебство: он применяет его к исходному, сломанному коммиту (исправляя его), а затем полностью удаляет уродливый коммит-заплатку!

fixup

Мы можем вместе разобрать практический пример! Допустим, выбранный коммит не работает.

Список коммитов

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

git add error.html 
git commit --fixup 2b504bee

Мы создаём новый коммит, но сообщаем Git, что это особенный коммит: это исправление для старого коммита с указанным SHA-1 хэшем (в нашем случае 2b504bee )

Второй шаг — начать сессию интерактивного перебазирования, потому что исправление относится к большому набору инструментов интерактивного перебазирования.

git rebase -i --autosquash 0023cddd

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

git rebase -i --autosquash

Благодаря опции —autosquash , Git уже сделал за нас тяжёлую работу:

  1. Он отметил наш небольшой временный коммит ключевым словом fixup . Таким образом, Git объединит его с приведённым выше коммитом, а затем отбросит его.
  2. Он также соответствующим образом изменил порядок строк, переместив наш временный коммит прямо перед коммитом, который мы хотим исправить (опять же: fixup работает путём объединения отмеченного коммита с предыдущим)

Короче: нам ничего не остаётся как закрыть окно редактора!

Давайте посмотрим на итоговый результат.

  • Сломанный коммит исправлен: содержит изменения подготовленные нами во временном коммите.
  • Уродливый «заплаточный» коммит был отброшен: история коммитов чиста и легко читается — как будто никакой ошибки не было.

Чистая история коммитов

Знание как исправлять ошибки — сверхсила

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

Получайте удовольствие от ошибок — и, конечно же, с лёгкостью исправляйте их!

  • Git: Руководство по исправлению ошибок (Часть 1)
  • Git: Руководство по исправлению ошибок (Часть 2)

Git. Коротко о главном

Привет, Хабр! Меня зовут Егор, я занимаюсь разработкой мобильных приложений на Flutter. Это моя первая работа в сфере IT, и как подобает начинающим, я столкнулся с проблемой изучения систем контроля версий. В данной публикации я хочу поделиться приобретенными знаниями и подробно рассмотреть одну из таких систем, а именно Git. Итак, начнем.

“Whoah, I’ve just read this quick tuto about git and oh my god it is cool. I feel now super comfortable using it, and I’m not afraid at all to break something.” — said no one ever.

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

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

Тем не менее, я бы хотел дополнить просторы интернета очередной статьей о Git. Постараюсь изложить все таким образом, как если бы у меня была возможность объяснить все самому себе из прошлого. Как следует из названия, я расскажу о Git очень коротко; а точнее о возможностях, которые он нам предоставляет.

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

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

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

1. Централизованные системы контроля версий;

2. Распределенные системы контроля версий.

Централизованная система контроля версий — это система, при которой репозиторий проекта хранится на сервере и вносить изменения вы можете непосредственно только в этот репозиторий при помощи специальных клиентских приложений. Среди таких систем можно выделить: ClearCase, TFVC, SVN.

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

Git является распределенной системой контроля версий, разработанной Линусом Торвальдсом для управления разработкой ядра Linux. На данный момент Git завоевал огромную популярность в IT сообществе и, как следствие, его часто можно встретить в стеке технологий различных компаний.

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

Установка Git

Прежде чем мы продолжим, вам необходимо установить Git.

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

# Если вы используете менеджер пакетов HomeBrew, # Вы можете выполнить следующую команду: brew install git # В противном случае вам достаточно ввести: git --version # После чего вам будет предложено установить Git 
  • Windows. Перейдите по ссылке и скачайте Git соответствующий архитектуре вашего процессора (32 или 64-bit) и установите его.
  • Linux. Перейдите по ссылке для более подробной инструкции.
# Установка на Linux зависит от дистрибутива который вы используете # Debian/Ubuntu apt-get install git # Fedora yum install git

Структура директории .git/

Как правило, ваша работа с Git будет начинаться с того, что вам потребуется проинициализировать Git директорию в своем проекте. Это делается с помощью команды:

Ее необходимо ввести в корне вашего проекта. Это создаст в текущем каталоге новый подкаталог .git со следующим содержанием:

Структура директории .git

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

В данном файле содержатся настройки Git репозитория. Например, здесь можно хранить email и имя пользователя.

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

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

4. info — exclude

Каталог info содержит файл exclude, в котором можно указывать любые файлы, и Git не станет добавлять их в свою историю. Это почти то же самое что и .gitingnore (возможно вы сталкивались с ним. Его можно найти в корневом каталоге вашего проекта), за тем исключением, что exclude не сохраняется в истории проекта, и вы не сможете им поделиться с другими.

Каталог refs хранит в себе копию ссылок на объекты коммитов в локальных и удаленных ветках.

Каталог logs хранит в себе историю проекта для всех веток в вашем проекте.

Каталог objects хранит в себе BLOB объекты, каждый из которых проиндексирован уникальным SHA.

Промежуточная область с метаданными, такими как временные метки, имена файлов, а также SHA файлов, которые уже упакованы Git. В эту область попадают файлы, над которыми вы работали, при выполнение команды git add .

Файл содержит ссылку на текущую ветку, в которой вы работаете

Каждый раз во время слияния в этот файл попадает SHA ветки, с которой проводилось слияние

Файл хранит в себе ссылки в виде SHA на ветки, которые участвовали в git fetch

Файл хранит в себе ссылки в виде SHA на ветки, которые участвовали в git merge

Файл содержит в себе последнее введенное вами сообщение коммита

Самые распространенные команды в Git.

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

1. Внести изменения в проект;

2. Добавить изменения в индекс(staging area) — git add (таким образом вы сообщаете Git какие именно изменения должны быть занесены в историю.)

2. Закоммитить изменения — git commit (сохранить изменения в историю проекта)

3. Запушить — git push (отправить результаты работы на удаленный сервер, чтобы другие разработчики тоже имели к ним доступ)

Итак, разберемся в этом подробнее. Проинициализировав Git репозиторий, вы начинаете вносить какие-то изменения в проект. Предположим, что вы создали файл `hello_world.txt` и работаете над его редактированием.

Введем git status и увидим следующее:

On branch master No commits yet Untracked files: (use "git add . " to include in what will be committed) hello_world.txt

Команда git status отображает состояние директории и индекса(staging area). Это позволяет определить, какие файлы в проекте отслеживаются Git, а также какие изменения будут включены в следующий коммит.

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

use “git add . ” to include in what will be committed

git add hello_world.txt

On branch master No commits yet Changes to be commited: (use "git rm --cached . " to unstage) new file: hello_world.txt

Файл добавлен в индекс. Теперь можно закоммитить внесенные изменения и оставить небольшое описание. Делается это командой:

git commit -m ‘first commit

Готово! Мы сделали наш первый коммит! Далее добавим в наш файл строку “Hello, World!”, и снова проверим git status:

On branch master Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) no changes added to commit (use "git add" and/or "git commit -a")

Теперь Git сообщает, что у нас есть измененный файл hello_world.txt . И теперь нам сново нужно добавить его в индекс и затем закоммитить.

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

Для начала вам нужно создать удаленный репозиторий. Как это реализовать в случае с GitHub подробно описано тут.

Далее необходимо добавить удаленный репозиторий в Git:

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

git remote add origin https://github.com/user/hello_world.git

В данном случае “origin” является коротким именем для удаленного репозитория, на которое он будет ссылаться. Вы можете выбрать совершенно любое имя — это не важно. “origin” это просто стандартное соглашение.

Осталось дело за малым — отправить результат нашей работы в репозиторий. Делается это следующим образом:

git push origin

Готово! Теперь история изменений вашего проекта будет храниться в удаленном репозитории.

Работа с историей

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

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

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

  • git log
  • git show
  • git reflog
  • git reset
  • git log

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

Если ввести git log без каких либо параметров, выглядит это примерно так:

commit 957e1132f57d83§dbd402faf3c858cf5ba8b335f (HEAD -> master) Author: egor Date: Fri Jul 16 13:25:21 1021 +0300 fourth commit commit ekd53dkcld4dkf334r3r3sefio5dk6kfl54dkf53 Author: egor Date: Fri Jul 16 13:22:25 2021 +0300 third commit commit dslf4453lk34jk34k3h5g34u6m5n75j7kj3l345k Date: Fri Jul 16 13:22:27 2021 +0300 second commit commit h4k4o5jk2lhkl234jkl6nkg6j4lh4gjbh6ll45k4 Author: egor Date: Fri Jul 16 13:21:32 2021 +0300 first commit

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

Хотите просмотреть последние три коммита? Пожалуйста:

commit ekd53dkcld4dkf334r3r3sefio5dk6kfl54dkf53 Author: egor Date: Fri Jul 16 13:22:25 2021 +0300 third commit commit dslf4453lk34jk34k3h5g34u6m5n75j7kj3l345k Date: Fri Jul 16 13:22:27 2021 +0300 second commit commit h4k4o5jk2lhkl234jkl6nkg6j4lh4gjbh6ll45k4 Author: egor Date: Fri Jul 16 13:21:32 2021 +0300 first commit

Есть необходимость вывести все в одну линию? Запросто:

git log —oneline

957e113 (HEAD -> main) fourth commit ekd53dk third commit dslf445 second commit h4k4o5j first commit

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

Команда git show используется для отображения полной информации о любом объекте в Git, будь то коммит или ветка. По умолчанию git show отображает информацию коммита, на который в данный момент времени указывает HEAD.

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

Итак, если ввести git show , мы получим следующий результат:

commit 957e1132f57d83§dbd402faf3c858cf5ba8b335f (HEAD -> master) Author: egor Date: Fri Jul 16 13:25:21 1021 +0300 fourth commit diff --git a/hello_world.txt b/hello_world.txt index b402110..d49b5d7 10044 --- a/hello_world.txt +++ b/hello_world.txt @@ -1,2 +1,3 @@ Hello world! Bye, bye! +See you soon!

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

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

git show 349de9d..957e113

commit 957e1132f57d83§dbd402faf3c858cf5ba8b335f (HEAD -> master) Author: egor Date: Fri Jul 16 13:25:21 1021 +0300 fourth commit diff --git a/hello_world.txt b/hello_world.txt index b402110..d49b5d7 10044 --- a/hello_world.txt +++ b/hello_world.txt @@ -1,2 +1,3 @@ Hello world! Bye, bye! +See you soon! commit ekd53dkcld4dkf334r3r3sefio5dk6kfl54dkf53 Author: egor Date: Fri Jul 16 13:22:25 2021 +0300 third commit diff --git a/hello_world.txt b/hello_world.txt index cd08755..b402110 100644 --- a/hello_world.txt +++ b/hello_world.txt @@ -1 +1,2 @@ Hello world! +Bye, bye!

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

git show —oneline

957e113 (HEAD -> master) fourth commit diff --git a/hello_world.txt b/hello_world.txt index b402110..d49b5d7 10044 --- a/hello_world.txt +++ b/hello_world.txt @@ -1,2 +1,3 @@ Hello world! Bye, bye! +See you soon! 

Таким образом, мы сократим id коммита, а также исключим авторство и дату коммита.

Подробнее с командой `git show` и с её параметрами можно ознакомиться перейдя по ссылке.

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

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

Это возможно за счет того, что git reflog хранит свою информацию на вашей машине отдельно от коммитов, поэтому при удалении чего-либо в истории, в сможете это найти в git reflog .

Вывод этой команды выглядит следующим образом:

957e113 (HEAD -> master) HEAD@: commit: fourth commit ekd53dk HEAD@: commit: third commt dslf445 HEAD@: commit: second commit h4k4o5j HEAD@: commit (intial): first commit 

Теперь давайте рассмотрим очень полезную команду `git reset`. Она позволяет откатить проект до определенной точки.

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

  • git reset —soft
  • git reset —mixed
  • git reset —hard

Рассмотрим их по порядку. Для этого сначала давайте вспомним, что такое index. Как я упоминал ранее, index — это временный файл, который фиксирует структуру Git проекта в определенный момент времени. Это важная деталь сейчас, поскольку команда git reset в зависимости от параметра прокидывает нас в истории проекта с соответствующими состояниями индекса.

1. В случае с —soft , содержимое вашего индекса, а также рабочей директории, остается неизменным. Это значит, что если мы откатимся назад на пару коммитов, мы изменим ссылку указателя HEAD на указанный коммит и все изменения, которые были до этого внесены, окажутся в индексе.

2. При использовании параметра —mixed , мы опять-таки изменим ссылку указателя HEAD, но все предыдущие изменения в индекс не попадут, а будут отслеживаться как не занесенные в индекс. Это дает возможность внести в индекс только те изменения, которые нам необходимы, что довольно удобно!

3. Если использовать команду git reset с параметром —hard , мы снова изменим ссылку указателя HEAD, но все предыдущие изменения не попадут ни в индекс, ни в зону отслеживаемых файлов. Это значит, что мы полностью сотрем все изменения, которые вносили ранее. Это также удобно, если вы знаете, что вам больше не пригодится ваша предыдущая работа над проектом.

Давайте вернемся к нашему репозиторию и рассмотрим следующий пример:

git log —oneline

957e113 (HEAD -> master) fourth commit ekd53dk third commit dslf445 second commit h4k4o5j first commit

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

git reset —soft 349de9d

Далее, проверим индекс:

On branch master Changes to be committed: (use "git restore --staged . " to unstage) modified: hello_world.txt

И снова git log —oneline :

dslf445 (HEAD -> master) second commit h4k4o5j first commit

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

Теперь повторим наши действия, но уже с параметром —mixed :

git reset —mixed 349de9d

Проверим git status:

On branch master Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: hello_world.txt

А также git log —oneline :

dslf445 (HEAD -> master) second commit h4k4o5j first commit

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

И в заключении повторим ту же последовательность действий с параметром —hard .

git reset —hard 349de9d

Снова проверяем git status :

On branch master nothing to commit, working tree clean

И git log —oneline :

dslf445 (HEAD -> master) second commit h4k4o5j first commit

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

И если посмотреть сейчас содержимое файла, то мы увидим единственную строку “Hello, world!”, которую мы с вами добавляли в файл во втором коммите.

Ветвление в Git

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

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

Давайте попробуем с этим поработать на нашем примере. У нас имеется следующая последовательность коммитов.

957e113 (HEAD -> master) fourth commit ekd53dk third commit dslf445 second commit h4k4o5j first commit

Git по умолчанию во время инициализации создает ветку master и уже ведет свою работу в ней. Мы можем в этом убедиться введя команду:

* master

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

Делается это при помощи команды git branch . Давайте создадим ветку “dev”:

Теперь введя команду git branch мы увидим следующее:

 dev * master

Звёздочкой Git указывает на текущую ветку, в которой мы работаем.

Для того чтобы переключиться на другую ветку используют команду git checkout . Давайте переключимся на ветку “dev”.

git checkout dev

Switched to branch 'dev'

Теперь внесем любые изменения в файл hello_world.txt и сделаем коммит, после чего посмотрим, как выглядят наши ветки после редактирования.

Взглянем на git log —oneline :

dece9c9 (HEAD -> dev) fifth commit 957e113 (master) fourth commit ekd53dk third commit dslf445 second commit h4k4o5j first commit

Как и следовало ожидать, в нашей истории появился еще один — пятый коммит.

Теперь перейдем на ветку master

git checkout master

И просмотрим git log —oneline , и убедимся в том что все осталось без изменений.

957e113 (HEAD -> master) fourth commit ekd53dk third commit dslf445 second commit h4k4o5j first commit

Помимо разделения истории в Git мы также можем соединять воедино два потока разработки. Это значит, что нашу проделанную работу в новой ветке мы можем слить обратно в master. Такой процесс слияния можно выполнить при помощи команды git merge . То есть, если мы хотим слить изменения из ветки “dev” в ветку “master”, нам необходимо перейти на ветку “master” и в ней выполнить:

Updating 957e113..dece9c9 Fast-forward hello_world.txt | 1 + 1 file chaged, 1 insertion(+)

Теперь если мы проверим git log —oneline , то убедимся в том, что новый коммит из ветки “dev” переместился в ветку “master”.

dece9c9 (HEAD -> master, dev) fifth commit 957e113 fourth commit ekd53dk third commit dslf445 second commit h4k4o5j first commit

Теперь от ненужной ветки можно избавиться и удалить её с помощью команды git branch -d .

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

Примеры ведения истории проекта

Моя статья подходит к концу, но перед завершением хочу отметить, что во многих командах существуют определенные соглашения по поводу ведения истории в Git.

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

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

1. Сообщение коммита:

Ниже представлен шаблон наших сообщений коммита:

Мы указываем дату совершения коммита и версию приложения для удобства поиска работы в истории.

Модификаторы формата коммита предоставляют информацию о том какой фронт работы был выполнен в этом коммите.

Мы используем следующие модификаторы:

  • Dev: — указывает на то, что в коммите велась разработка нового функционала.
  • Refactoring: — данный модификатор сообщает о рефакторинге проведенном в коде.
  • Fix: — в данном коммите фиксили баги.
  • Release: — данный коммит отправлен в ветку «release» и хранит состояние релизной версии приложения.

Также в конце сообщения мы оставляем короткое описание — над чем мы работали в этом коммите.

2. Стратегия ветвления:

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

В нашем случае, мы выделяем две основные ветки master и «release». Master используется для подготовки к выкладке новых версий приложения. Код попавший в «master» проходит автоматические тесты, после которых выполняется сборка проекта, которую необходимо вручную протестировать перед дальнейшими действиями. Далее если замечаний к работе нет, мы сливаем ветку «master» в ветку «release». Там снова запускаются автоматические тесты, и собираются сборки к выкладке в маркеты.

Для ведения разработки мы создаем feature векти. Это означает, что каждая ветка отвечает за разработку какой-нибудь функциональности. Например, если мы хотим внедрить в приложение хранение данных в облаке, то программист создаст ветку «feature-cloud» и будет вести работу в ней.

Заключение

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

Надеюсь, вам было интересно. Хочу снова заметить, что Git — тема комплексная, и, собирая информацию по крупицам, вы в итоге сможете работать уверенно с этим инструментом. Главное здесь — практика и желание во всем разобраться.

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

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

1. “Version control with Git” — Jon Loeliger;

2. “Pro Git” — Scott Chacon, Ben Straub.

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

Спасибо за ваше внимание!

A3.11 Приложение C: Команды Git — Администрирование

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

git gc

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

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

git fsck

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

Мы лишь однажды использовали её в разделе Восстановление данных главы 10 для поиска более недостижимых (dangling) объектов.

git reflog

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

В основном, мы рассматривали эту команду в разделе RefLog-сокращения главы 7, где мы показали пример использования этой команды, а также как использовать git log -g для просмотра той же информации, используя git log .

Мы на практике рассмотрели восстановление потерянной ветки в разделе Восстановление данных главы 10.

git filter-branch

Команда git filter-branch используется для переписывания содержимого коммитов по заданному алгоритму, например, для полного удаления файла из истории или для вычленения истории лишь части файлов в проекте для вынесения в отдельный репозиторий.

В разделе Удаление файла из каждого коммита главы 7 мы объяснили механизм работы этой команды и рассказали про использование опций —commit-filter , —subdirectory-filter и —tree-filter .

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

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