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

Добавил пользователь Skiper
Обновлено: 05.10.2024

Коммит - очередное зафиксированное состояние проекта, "единица" версии.
Все коммиты (кроме первого) должны наследоваться от предыдущего коммита, образуя таким образом древовидную структуру, как изображено на рисунке ниже (кружки - коммиты).

Как видно из иллюстрации, проект может разветвляться, например если два разработчика параллельно работают и каждый создаёт свои коммиты. Чтобы не возникало полного хаоса и можно было ориентироваться в происходящем вводят понятие ветки
Ветка - по большому счёту просто именованная ссылка на некий коммит, указывающая на конец очередного ответвления от главной центральной ветки (по умолчанию она зовётся master). Как правило, репозиторий работает в привязке к какой-то ветке и при создании нового коммита, он присоединяется к тому, на который ссылается ветка, и ветка начинает указывать на новый коммит. На картинке выше помимо master есть ветки Little Feature и Big Feature.

Установка

Linux — нужно просто открыть терминал и установить приложение при помощи пакетного менеджера вашего дистрибутива. Для Ubuntu команда будет выглядеть следующим образом:

Windows — мы рекомендуем git for windows, так как он содержит и клиент с графическим интерфейсом, и эмулятор bash.

Настройка

Репозиторий

Итак, вот у вас уже есть git. Теперь нужно создать хранилище версий для него. Запомните, это хранилище называется репозиторий (англ. repository) — при случае можете вставить где-нибудь это словечко. В зависимости от того, какая у вас оболочка, соответствующей командой создайте новую директорию, откройте ее (в командной строке, она же оболочка, а не проводником или чем-то подобным) и выполните:

Все, локальный репозиторий в этой папке создан. То, что здесь сейчас хранится, будет бекапом, поэтому, чтобы его не испортить, создадим рабочую копию (англ. check out)локальной версии:

Где [url] — это путь до клонируемого репозитория. Мы разбираем сейчас случай, когда вы создаете рабочую копию собственного репозитория, поэтому в качестве [url] здесь вам нужно указать путь до директории, для которой мы выполняли git init.

Еще иногда может потребоваться склонировать репозиторий без многолетней истории его коммитов, тогда нужно использовать параметр --depth=5, где 5 - количество коммитов от последнего:

  1. Создание репозитория (git init) или (git clone адресс_репозитория ), если копируем удалённый
  2. Делаем изменения
  3. Помещаем файлы под VCS-отслеживание (git add)
  4. Фиксируем (коммитим) изменения (git commit)
  5. Заливаем (пушим) их на удалённое хранилище (git push)

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

Файл(-ы) находятся в HEAD вашей рабочей локальной копии. В вашем удаленном репозитории их все еще нет.
Пуш в репозиторий:

Ветвление

Создание новой ветки
Есть разные принципы модели ветвления в git. Одна из них: Новая задача - новая ветка. О другой поговорим далее.
Создание новой ветки:

Обязательно нужно делать пуш изменений в общий репозиторий:

Запрос изменений с сервера

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

Слияние веток

Ветки можно сравнить:

Разрешение конфликтов при слиянии

git merge 1_branch
Auto-merging print_array.js
CONFLICT (content): Merge conflict in print_array.js
Automatic merge failed; fix conflicts and then commit the result.

Система не смогла разрешить конфликт автоматически, значит, это придется сделать разработчикам. Приложение отметило строки, содержащие конфликт:
Над разделителем ======= мы видим последний (HEAD) коммит, а под ним — конфликтующий. Таким образом, мы можем увидеть, чем они отличаются и решать, какая версия лучше. Или вовсе написать новую. В этой ситуации мы так и поступим, перепишем все, удалив разделители, и дадим git понять, что закончили.Когда все готово, нужно закоммитить изменения, чтобы закончить процесс:

Короткая и простая история коммитов.

git checkout -b iss53

Создание новой ветки / указателя.


Сделали новый коммит:

Ветка iss53 передвинулась вперёд во время работы.


Создание хот-фикса:
git checkout master
git checkout -b hotfix

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


Слияние веток:
git checkout master
git merge hotfix
git merge iss53

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

Настройка .gitignore

  1. Создайте вручную файл под названием .gitignore и сохраните его в директорию проекта.
  2. Внутри файла перечислите названия файлов/папок, которые нужно игнорировать, каждый с новой строки.
  3. Файл .gitignore должен быть добавлен, закоммичен и отправлен на сервер, как любой другой файл в проекте.
  • Логи
  • Артефакты систем сборки
  • Папки node_modules в проектах node.js
  • Папки, созданные IDE, например, Netbeans или IntelliJ
  • Разнообразные заметки разработчика.

*.log
build/
node_modules/
.idea/
my_notes.txt

Удачная модель ветвления для Git

  • master - создаётся при инициализации репозитория, считаем ветку origin/master главной.
  • develop - ветвь origin/develop мы считаем главной ветвью для разработки.
  • Ветви функциональностей (Feature branches)
  • Ветви релизов (Release branches)
  • Ветви исправлений (Hotfix branches)

При начале работы над новой функциональностью делается ответвление от ветви разработки (develop).

Ветви релизов (release branches)
Могут порождаться от: develop
Должны вливаться в: develop и master
Соглашение о наименовании: release-*

Ветвь релиза создаётся из ветви разработки (develop).
Закрытие ветви релиза
Когда мы решаем, что ветвь релиза (release branch) окончательно готова для выпуска, нужно проделать несколько действий. В первую очередь ветвь релиза вливается в главную ветвь (напоминаю, каждый коммит в master — это по определению новый релиз). Далее, этот коммит в master должен быть помечен тегом, чтобы в дальнейшем можно было легко обратиться к любой существовавшей версии продукта. И наконец, изменения, сделанные в ветви релиза (release branch), должны быть добавлены обратно в разработку (ветвь develop), чтобы будущие релизы также содержали внесённые исправления багов.

Switched to branch 'master'
git merge --no-ff release-1.2
Merge made by recursive.
(Отчёт об изменениях)

git tag -a 1.2

Теперь релиз издан и помечен тегом.

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

Switched to branch 'develop'

git merge --no-ff release-1.2

Merge made by recursive.
(Отчёт об изменениях)

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

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

Deleted branch release-1.2 (was ff452fe).

Ветви исправлений (hotfix branches)
Могут порождаться от: master
Должны вливаться в: develop и master
Соглашение о наименовании: hotfix-*

Ветви исправлений (hotfix branches) создаются из главной (master) ветви.

Заключение

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

Краткая справка команд:

git pull - обновить данные из серверного репозитория
git add - добавить в список "на коммит"
git commit - создание пакета (коммита) с изменениями
git push - залить за серверный (удалённый) репозиторий
git merge BRANCH - слияние ветки в который ты находишься, с веткой BRANCH


Вопросы:
Есть репозиторий, над ним работают два человека: первый клонирует репозиторий, вносит правки и пушит; второй в это же время тоже начал работу, склонировал, но запушить не может, так как 1й уже внес правки. Как быть?

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


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

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

Потом сделать:
git add .
git commit
(в комите можно написать комментарий типа "фикс конфликтов")
git push

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

Комментарии:

Отправитель: anonymous git reset --hard HEAD - сброс незакоммиченных изменений

Отправитель: anonymous Спасибо. Кратко и всё по делу.

Отправитель: anonymous ты ты ты ты ты

Отправитель: anko В Git есть специальная команда cherry-pick, которая позволяет вставлять в текущую ветку изменения из любого коммита. Работает она так:
git cherry-pick test

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

Система контроля версий Git

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

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

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

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

В Windows их две: PowerShell и cmd.exe. В Ubuntu это Terminal. Самая популярная программа на macOS тоже называется Terminal. Если вам не подходит встроенная в систему программа для работы с командной строкой, вы можете поставить свою. Например, написанную на JavaScript программу Hyper, которая работает на любой операционной системе. На Windows популярны программы Cmder и Git Bash, а на macOS — iTerm.

Git — важный навык веб-разработчика

Устанавливаем Git

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

Установка в Windows

Скачайте exe-файл инсталлятора с сайта Git и запустите его. Это Git для Windows, он называется msysGit. Установщик спросит добавлять ли в меню проводника возможность запуска файлов с помощью Git Bash (консольная версия) и GUI (графическая версия). Подтвердите действие, чтобы далее вести работу через консоль в Git Bash. Остальные пункты можно оставить по умолчанию.

Установка на macOS

Установка в Linux

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

  • Если у вас 21 или более ранняя версия Fedora, используйте yum install git .
  • Для 22 и последующих версий Fedora вводите dnf install git .
  • Для дистрибутивов, основанных на Debian, например, Ubuntu, используйте apt-get: sudo apt-get install git .

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

Проверим, что Git установлен

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

Настройка Git

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

Откройте терминал и используйте следующую команду, чтобы добавить своё имя: git config --global user.name "ваше имя"

Для добавления почтового адреса вводите: git config --global user.email адрес

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

Что такое GitHub?

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

Чтобы начать работу с GitHub, нужно зарегистрироваться на сайте, если вы ещё этого не сделали. За дело.

  1. Переходим на сайт GitHub. Cтартовая страница GitHub.
  2. Для начала регистрации:
    • Нажимаем кнопку Sign up (зарегистрироваться), попадаем на страницу регистрации, где вводим обязательные данные: имя пользователя, адрес электронной почты и пароль. После заполнения полей проходим верификацию. Первый шаг регистрации профиля на стартовой странице GitHub.
    • После заполнения данных и успешного прохождения верификации нажимаем на кнопку Select a plan. Второй шаг регистрации профиля на стартовой странице GitHub.
  3. Третий шаг — небольшой опрос от GitHub, который вы можете пройти, заполнив все поля и нажать Submit или пропустить, нажав skip this step. Опрос на третьем шаге регистрации.
  4. После прохождения всех этапов на сайте, на указанный при регистрации ящик вам придёт письмо от GitHub. Откройте его и подтвердите свой почтовый адрес, нажав Verify email address (подтвердить электронный адрес) или скопируйте вспомогательную ссылку из письма и вставьте её в адресную строку браузера. Подтверждение электронного адреса.
  5. После верификации GitHub предложит создать новый репозиторий, организацию или узнать больше о GitHub. Этот пункт пока можно пропустить и перейти в профиль. Переход в ваш профиль. Так выглядит ваш профиль после регистрации.

Теперь у вас есть профиль на GitHub.

Устанавливаем SSH-ключи

Git установлен, профиль на GitHub создан. Осталось добавить SSH-ключ и можно приступать к работе с проектом.

Что такое SSH-ключ и зачем он нужен?

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

Каждый SSH-ключ содержит пару: открытый (публичный) и закрытый (приватный) ключ. Открытый ключ отправляется на сервер, его можно не прятать от всех и не переживать, что кто-то его увидит и украдёт. Он бесполезен без своей пары — закрытого ключа. А вот закрытый ключ — секретная часть. Доступ к нему должен быть только у вас.

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

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

Сначала проверим, есть ли уже на компьютере ключ. По умолчанию SSH-ключи хранятся в каталоге ~/.ssh , поэтому нужно проверить содержимое этого каталога.

В Сmder для запуска ssh-agent можно использовать команду start-ssh-agent .

Если проблема осталась, рекомендуем работать в Git Bash.

Вы можете добавить свой приватный ключ в ssh-agent и сохранить пароль к нему с помощью команды ssh-add -K ~/.ssh/id_rsa . Если у вашего ключа другое имя, не забудьте заменить id_rsa в команде на правильное название.

Можно пойти другим путём, открыть файл id_rsa.pub прямо в папке и просто скопировать содержимое оттуда.

Нажимаем кнопку New SSH key (новый SSH-ключ). Вводим имя ключа (можно придумать абсолютно любое) в поле Title (название), а в Key (ключ) вставляем сам ключ из буфера обмена. Теперь нажимаем Add SSH key (добавить SSH-ключ).

Добавляем в свой профиль SSH-ключ

Добавляем в свой профиль SSH-ключ.

Если всё сделано верно, в списке появится новый ключ.

Теперь, наконец-то, мы можем начать работу с самим проектом.

Работа с репозиториями

Для начала определим, что такое репозиторий

Это рабочая директория с вашим проектом. По сути, это та же папка с HTML, CSS, JavaScript и прочими файлами, что хранится у вас на компьютере, но находится на сервере GitHub. Поэтому вы можете работать с проектом удалённо на любой машине, не переживая, что какие-то из ваших файлов потеряются — все данные будут в репозитории при условии, что вы их туда отправите. Но об этом позже.

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

Как сделать форк мастер-репозитория?

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

Открываем консоль, переходим в директорию, где хотим сохранить папку с проектом, и вводим команду:

Если вы правильно настроили SSH-ключи, Git начнёт процесс копирования репозитория на ваш компьютер. Если вы видите ошибку, в которой написано Error: Permission denied (publickey) , скорее всего, вы ошиблись где-то при выполнении инструкции по настройке SSH-ключа. Вернитесь на несколько абзацев ранее и попробуйте повторить процесс настройки.

Если вы не хотите вручную вводить адрес репозитория, вы можете зайти на страницу проекта, нажать зелёную кнопку Clone or download (клонировать или скачать), выбрать Clone with SSH (клонировать по SSH) и скопировать адрес, который находится в текстовом поле. Этот адрес вы можете вставить в команду git clone .

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

Теперь, на вашем компьютере, в папке your_project или в той, название которой вы указали самостоятельно, находится полная копия репозитория c GitHub.

Чтобы начать работу с проектом, надо оказаться в его директории. Для этого используем команду cd , после которой указываем название проекта на вашем компьютере: cd your-project

 Копия репозитория

Сделали копию репозитория.

Создадим новую ветку. Открываем терминал, вводим команду git branch . Она показывает список веток, с которыми мы работаем в проекте, и выделяет текущую. Если мы находимся в master создаём новую ветку: git checkout -b имя-новой-ветки .

 Новая ветка

Новая ветка.

Если текущая ветка не master , сначала переключимся в основную ветку: git checkout master . Мы делаем это, чтобы новая ветка содержала свежую, на момент создания, рабочую версию проекта.

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

 Переключаемся между ветками

Переключаемся между ветками.

Если вы ошиблись в названии, например, допустили опечатку, вы можете изменить название ветки с помощью команды: git branch -m старое-имя-ветки новое-имя-ветки .

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

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

 Состояние ветки

Состояние ветки.

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

Если вы хотите сохранить все изменения разом, вводите git add -A .

Делаем коммит

Делаем коммит.

Сохранения зафиксированы, всё? Они теперь в репозитории и видны коллегам? Пока нет. Те изменения, которые мы внесли и сохранили, пока локальны. Их нужно послать на GitHub.

 Отправляем изменения

Отправляем изменения.

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

Любое предложение можно принять или отвергнуть. Так же и с пулреквестом. После его создания, он должен получить ревью и одобрение так называемого коллаборатора — пользователя GitHub, который имеет права администратора в мастер-репозитории. Им может быть ваш коллега-разработчик, техлид, наставник. Если к вашему коду нет вопросов, пулреквест принимается и изменения из вашей ветки попадают в master главного репозитория. Если в код нужно внести изменения, пулреквест отклоняется, и вам нужно снова пройти по цепочке локальные изменения — сохранение — коммит — пуш, только пулреквест заново делать не нужно. Если вы продолжаете вести работу в той же ветке и пулреквест ещё не принят, все ваши изменения автоматически добавятся в пулреквест, созданный из этой ветки после команды git push origin название-текущей-ветки .

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

  1. В локальном репозитории вводим команду git checkout master , переходим в master .
  2. Теперь забираем (подтягиваем) изменения из ветки master мастер-репозитория git pull academy master . Academy здесь — сокращённое название мастер-репозитория, такое имя используется в проектах студентов Академии, вы можете выбрать любое другое название. Забираем изменения из мастер-репозитория. Если консоль выдаёт ошибку и говорит, что не знает директории с таким именем, нужно добавить ссылку на этот репозиторий: Вместо academy указывайте своё название и оно закрепится за этим репозиторием.
  3. Теперь отправьте изменения уже из своей ветки master в ваш форк на GitHub с помощью команды git push origin master . Отправляем изменения в форк.

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

Шпаргалка по Git

Результат: каталог с выписанной веткой master . Теперь можно создавать новые ветки, или выписывать с github существующие.

Как выписать ветку с github

Или так, что намного надежнее:

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

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

Т.е. сначала мы создаем новую ветку, а затем вливаем в нее изменения из ветки на github.

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

2. Публикуем ее на github:

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

Если вы случайно удалили какой-то файл, можно извлечь его из хранилища:

Как посмотреть список веток

Как сделать commit

Создаем новую ветку, выполняем в ней нужные изменения.

  1. Список всех измененных и добавленных файлов можно просмотреть командой:

2. Подготавливаем коммит, добавляя в него файлы командой:

Или удаляем устаревшие файлы:

3. Выполняем коммит:

4. Как правило, в репозитории существует две основные ветки — dev и master. Dev — общая ветка разработчиков и тестировщиков. Именно в нее добавляются все новые разработки перед очередным релизом. Master — ветка для выкладки продукта на боевые сервера.

После коммита надо влить в нашу ветку изменения из ветки dev и master:

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

5. Переключаемся на ветку dev:

6. Вливаем в dev изменения из ветки проекта:

7. Заливаем последнюю версию ветки dev на удаленный сервер:

push может не пройти, потому что удалённый origin/dev обогнал локальную его копию.

Как решить конфликт бинарных файлов

Допустим, при слиянии с другой веткой git выдал ошибку. Команда git status возвращает информацию о конфликте:

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

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

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

Как посмотреть историю изменений

git log — просмотр логов.

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

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

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

Можно посмотреть построчную информацию о последнем коммите, имя автора и хэш коммита:

git annotate, выводит измененные строки и информацию о коммитах, где это произошло:

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

  1. git log — просмотр логов, показывает дельту (разницу/diff), привнесенную каждым коммитом.
  1. Копируем идентификатор коммита, до которого происходит откат.
  2. Откатываемся до последнего успешного коммита (указываем последний коммит):

Можно откатить до последней версии ветки:

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

Как выполнить слияние с другой веткой

git merge выполняет слияние текущей и указанной ветки. Изменения добавляются в текущую ветку.

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

git pull отличается от git merge тем, что merge только выполняет слияние веток, а pull прежде чем выполнить слияние — закачивает изменения с удаленного сервера. merge удобно использовать для слияния веток в локальном репозитории, pull — слияния веток, когда одна из них лежит на github.

Создание нового локального репозитория

git cherry-pick

git cherry-pick помогает применить один-единственный коммит из одной ветки к дереву другой.

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

3. Выполнить команду, указать код коммита:

4. После этого обновить ветку на сервере:

Как раскрасить команды git

После создания репозитория в текущей директории появится субдиректория .git . Она содержит файл config .

Чтобы раскрасить вывод git, можно добавить в файл блок [color] :

Add colors to your ~/.gitconfig file:

Highlight whitespace in diffs

Add aliases to your ~/.gitconfig file:

[alias] st = status
ci = commit
br = branch
co = checkout
df = diff
dc = diff —cached
lg = log -p
lol = log —graph —decorate —pretty=oneline —abbrev-commit
lola = log —graph —decorate —pretty=oneline —abbrev-commit —all
ls = ls-files

git config -e [—global] edit the .git/config [or ~/.gitconfig] file in your $EDITOR

git config —global user.name ‘John Doe’
git config —global user.email [email protected]
sets your name and email for commit messages

git config core.autocrlf true
This setting tells git to convert the newlines to the system’s standard
when checking out files, and to LF newlines when committing in

git config —list
To view all options

git config apply.whitespace nowarn
To ignore whitespace

Info
—-
git reflog
Use this to recover from *major* mess ups! It’s basically a log of the
last few actions and you might have luck and find old commits that
have been lost by doing a complex merge.

git status
show files added to the staging area, files with changes, and untracked files

git show
show the changeset (diff) of a commit specified by , which can be any
SHA1 commit ID, branch name, or tag (shows the last commit (HEAD) by default)

also to show the contents of a file at a specific revision, use
git show :
this is similar to cat-file but much simpler syntax.

git show —name-only
show only the names of the files that changed, no diff information.

git blame
show who authored each line in

git blame
show who authored each line in as of (allows blame to go back in
time)

git gui blame
really nice GUI interface to git blame

git whatchanged
show only the commits which affected listing the most recent first
E.g. view all changes made to a file on a branch:
git whatchanged
| grep commit | \
colrm 1 7 | xargs -I % git show %
this could be combined with git remote show to find all changes on
all branches to a particular file.

git diff head path/to/fubar
show the diff between a file on the current branch and potentially another branch

git diff —cached [ ] shows diff for staged (git-add’ed) files (which includes uncommitted git cherry-pick’ed files)

git ls-files
list all files in the index and under version control.

git ls-remote [HEAD] show the current version on the remote repo. This can be used to check whether
a local is required by comparing the local head revision.

git add …
add , , etc… to the project

git add
add all files under directory to the project, including subdirectories

git add .
add all files under the current directory to the project
*WARNING*: including untracked files.

git rm …
remove , , etc… from the project

git rm $(git ls-files —deleted)
remove all deleted files from the project

git rm —cached …
commits absence of , , etc… from the project

Edit $GIT_DIR/.git/info/exclude. See Environment Variables below for explanation on $GIT_DIR.

Add a file .gitignore to the root of your project. This file will be checked in.

Either way you need to add patterns to exclude to these files.

git add …
git stage …
add changes in , … to the staging area (to be included in
the next commit

git add -p
git stage —patch
interactively walk through the current changes (hunks) in the working
tree, and decide which changes to add to the staging area.

git add -i
git stage —interactive
interactively add files/changes to the staging area. For a simpler
mode (no menu), try `git add —patch` (above)

git reset HEAD …
remove the specified files from the next commit

git commit … [-m ] commit , , etc…, optionally using commit message ,
otherwise opening your editor to let you type a commit message

git commit -a
commit all files changed since your last commit
(does not include new (untracked) files)

git commit -v
commit verbosely, i.e. includes the diff of the contents being committed in
the commit message screen

git commit —amend
edit the commit message of the most recent commit

git commit —amend …
redo previous commit, including changes made to , , etc…

git branch
list all local branches

git branch -r
list all remote branches

git branch -a
list all local and remote branches

create a new branch named
, referencing the same point in history as
the current branch

git branch

create a new branch named
, referencing , which may be
specified any way you like, including using a branch name or a tag name

git push :refs/heads/

git branch —track

create a tracking branch. Will push/pull changes to/from another repository.
Example: git branch —track experimental origin/experimental

git branch —set-upstream
(As of Git 1.7.0)
Make an existing branch track a remote branch
Example: git branch —set-upstream foo origin/foo

delete the branch
; if the branch you are deleting points to a
commit which is not reachable from the current branch, this command
will fail with a warning.

git branch -r -d
delete a remote-tracking branch.
Example: git branch -r -d wycats/master

even if the branch points to a commit not reachable from the current branch,
you may know that that commit is still reachable from some other branch or
tag. In that case it is safe to use this command to force git to delete the
branch.

make the current branch
, updating the working directory to reflect
the version referenced by

git checkout -b
create a new branch referencing , and check it out.

removes a branch from a remote repository.
Example: git push origin :old_branch_to_be_deleted


Checkout a file from another branch and add it to this branch. File
will still need to be added to the git branch, but it’s present.
Eg. git co remote_at_origin__tick702_antifraud_blocking …./…nt_elements_for_iframe_blocked_page.rb


Eg. git show remote_tick702 — path/to/fubar.txt
show the contents of a file that was created on another branch and that
does not exist on the current branch.

git show :
Show the contents of a file at the specific revision. Note: path has to be
absolute within the repo.

merge branch
into the current branch; this command is idempotent
and can be run as many times as needed to keep the current branch
up-to-date with changes in

git merge
—no-commit
merge branch
into the current branch, but do not autocommit the
result; allows you to make further tweaks

git merge
-s ours
merge branch
into the current branch, but drops any changes in

, using the current tree as the new tree

git cherry-pick [—edit] [-n] [-m parent-number] [-s] [-x]
selectively merge a single commit from another local branch
Example: git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544

git hash-object
get the blob of some file whether it is in a repository or not

Find the commit in the repository that contains the file blob:

git mergetool
work through conflicted files by opening them in your mergetool (opendiff,
kdiff3, etc.) and choosing left/right chunks. The merged result is staged for
commit.

For binary files or if mergetool won’t do, resolve the conflict(s) manually
and then do:

Once all conflicts are resolved and staged, commit the pending merge with:

git push
update the server with your commits across all branches that are *COMMON*
between your local copy and the server. Local branches that were never
pushed to the server in the first place are not shared.

git push origin

git push origin
:refs/heads/

E.g. git push origin twitter-experiment:refs/heads/twitter-experiment
Which, in fact, is the same as git push origin
but a little
more obvious what is happening.

git checkout
re-checkout , overwriting any local changes

Fix mistakes / Undo
——————-

git reset —hard
abandon everything since your last commit; this command can be DANGEROUS.
If merging has resulted in conflicts and you’d like to just forget about
the merge, this command will do that.

git reset —soft HEAD^
forgot something in your last commit? That’s easy to fix. Undo your last
commit, but keep the changes in the staging area for editing.

git commit —amend
redo previous commit, including changes you’ve staged in the meantime.
Also used to edit commit message of previous commit.

test = $(git merge-base )
determine if merging sha1-B into sha1-A is achievable as a fast forward;
non-zero exit status is false.

git stash apply
restore the changes recorded in the stash on top of the current working tree
state

git stash pop
restore the changes from the most recent stash, and remove it from the stack
of stashed changes

git stash list
list all current stashes

git stash show -p
show the contents of a stash — accepts all diff args

git stash drop [ ] delete the stash

git stash clear
delete all current stashes

git push :refs/heads/

delete a branch in a remote repository

git push :refs/heads/
create a branch on a remote repository
Example: git push origin origin:refs/heads/new_feature_name

git push + :
replace a branch with
think twice before do this
Example: git push origin +master:my_branch

git remote show
show information about the remote server.

git checkout -b /
Eg.:
git checkout -b myfeature origin/myfeature
git checkout -b myfeature remotes/ /

Track a remote branch as a local branch. It seems that
somtimes an extra ‘remotes/’ is required, to see the exact
branch name, ‘git branch -a’.

git push
For branches that are remotely tracked (via git push) but
that complain about non-fast forward commits when doing a
git push. The pull synchronizes local and remote, and if
all goes well, the result is pushable.

git fetch
Retrieves all branches from the remote repository. After
this ‘git branch —track …’ can be used to track a branch
from the new remote.

git submodule add


add the given repository at the given path. The addition will be part of the
next commit.

git submodule update [—init] Update the registered submodules (clone missing submodules, and checkout
the commit specified by the super-repo). —init is needed the first time.

git submodule foreach
Executes the given command within each checked out submodule.

1. Delete the relevant line from the .gitmodules file.
2. Delete the relevant section from .git/config.
3. Run git rm —cached path_to_submodule (no trailing slash).
4. Commit and delete the now untracked submodule files.

Updating submodules
To update a submodule to a new commit:
1. update submodule:
cd


git pull
2. commit the new version of submodule:
cd

git format-patch HEAD^
Generate the last commit as a patch that can be applied on another
clone (or branch) using ‘git am’. Format patch can also generate a
patch for all commits using ‘git format-patch HEAD^ HEAD’
All page files will be enumerated with a prefix, e.g. 0001 is the
first patch.

git format-patch ^..
Generate a patch for a single commit. E.g.
git format-patch d8efce43099^..d8efce43099
Revision does not need to be fully specified.


Applies the patch file generated by format-patch.

git diff —no-prefix > patchfile
Generates a patch file that can be applied using patch:
patch -p0
Will checkout the code for a particular tag. After this you’ll
probably want to do: ‘git co -b ’ to define
a branch. Any changes you now make can be committed to that
branch and later merged.

git archive master | tar -x -C /somewhere/else
Will export expanded tree as tar archive at given path

git archive master | bzip2 > source-tree.tar.bz2
Will export archive as bz2

git archive —format zip —output /full/path master
Will export as zip

GIT_AUTHOR_NAME, GIT_COMMITTER_NAME
Your full name to be recorded in any newly created commits. Overrides
user.name in .git/config

GIT_AUTHOR_EMAIL, GIT_COMMITTER_EMAIL
Your email address to be recorded in any newly created commits. Overrides
user.email in .git/config

GIT_DIR
Location of the repository to use (for out of working directory repositories)

GIT_WORKING_TREE
Location of the Working Directory — use with GIT_DIR to specifiy the working directory root
or to work without being in the working directory at all.

Change author for all commits with given name

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

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

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

Жизненный цикл состояний файлов

Определение состояния файлов

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

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

Предположим, вы добавили в свой проект новый файл, простой файл README . Если этого файла раньше не было, и вы выполните git status , вы увидите свой неотслеживаемый файл вот так:

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

Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда git add . Чтобы начать отслеживание файла README , вы можете выполнить следующее:

Если вы снова выполните команду status , то увидите, что файл README теперь отслеживаемый и добавлен в индекс:

Индексация изменённых файлов

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

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

Что за чёрт? Теперь CONTRIBUTING.md отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно? Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду git add . Если вы выполните коммит сейчас, то файл CONTRIBUTING.md попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду git add , а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения git commit . Если вы изменили файл после выполнения git add , вам придётся снова выполнить git add , чтобы проиндексировать последнюю версию файла:

Сокращенный вывод статуса

Вывод команды git status довольно всеобъемлющий и многословный. Git также имеет флаг вывода сокращенного статуса, так что вы можете увидеть изменения в более компактном виде. Если вы выполните git status -s или git status --short вы получите гораздо более упрощенный вывод:

Новые неотслеживаемые файлы помечены ?? слева от них, файлы добавленные в отслеживаемые помечены A , отредактированные файлы помечены M и так далее. В выводе содержится два столбца — в левом указывается статус файла, а в правом модифицирован ли он после этого. К примеру в нашем выводе, файл README модифицирован в рабочем каталоге, но не проиндексирован, а файл lib/simplegit.rb модифицирован и проиндексирован. Файл Rakefile модифицирован, проиндексирован и ещё раз модифицирован, таким образом на данный момент у него есть те изменения, которые попадут в коммит, и те, которые не попадут.

Игнорирование файлов

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

К шаблонам в файле .gitignore применяются следующие правила:

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

Чтобы избежать рекурсии используйте символ слеш (/) в начале шаблона.

Чтобы исключить каталог добавьте слеш (/) в конец шаблона.

Можно инвертировать шаблон, использовав восклицательный знак (!) в качестве первого символа.

Glob-шаблоны представляют собой упрощённые регулярные выражения, используемые командными интерпретаторами. Символ ( * ) соответствует 0 или более символам; последовательность [abc] — любому символу из указанных в скобках (в данном примере a, b или c); знак вопроса ( ? ) соответствует одному символу; и квадратные скобки, в которые заключены символы, разделённые дефисом ( 6 ), соответствуют любому символу из интервала (в данном случае от 0 до 9). Вы также можете использовать две звёздочки, чтобы указать на вложенные каталоги: a/**/z соответствует a/z , a/b/z , a/b/c/z , и так далее.

Вот ещё один пример файла .gitignore :

В простейшем случае репозиторий будет иметь один файл .gitignore в корневом каталоге, правила из которого будут рекурсивно применяться ко всем подкаталогам. Так же возможно использовать .gitignore файлы в подкаталогах. Правила из этих файлов будут применяться только к каталогам, в которых они находятся. Например, репозиторий исходного кода ядра Linux содержит 206 файлов .gitignore .

Детальное рассмотрение использования нескольких .gitignore файлов выходит за пределы этой книги; детали доступны в справке man gitignore .

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

Допустим, вы снова изменили и проиндексировали файл README , а затем изменили файл CONTRIBUTING.md без индексирования. Если вы выполните команду git status , вы опять увидите что-то вроде:

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

Эта команда сравнивает содержимое вашего рабочего каталога с содержимым индекса. Результат показывает ещё не проиндексированные изменения.

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

Важно отметить, что git diff сама по себе не показывает все изменения сделанные с последнего коммита — только те, что ещё не проиндексированы. Такое поведение может сбивать с толку, так как если вы проиндексируете все свои изменения, то git diff ничего не вернёт.

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

Используйте git diff для просмотра непроиндексированных изменений

а так же git diff --cached для просмотра проиндексированных изменений ( --staged и --cached синонимы):

Мы будем продолжать использовать команду git diff различными способами на протяжении всей книги. Существует еще один способ просматривать эти изменения, если вы предпочитаете графический просмотр или внешнюю программу просмотра различий, вместо консоли. Выполнив команду git difftool вместо git diff , вы сможете просмотреть изменения в файле с помощью таких программ как emerge, vimdiff и других (включая коммерческие продукты). Выполните git difftool --tool-help чтобы увидеть какие из них уже установлены в вашей системе.

Коммит изменений

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

Эта команда откроет выбранный вами текстовый редактор.

Редактор устанавливается переменной окружения EDITOR — обычно это vim или emacs, хотя вы можете установить любой другой с помощью команды git config --global core.editor , как было показано в главе Введение).

В редакторе будет отображён следующий текст (это пример окна Vim):

Для ещё более подробного напоминания, что же именно вы поменяли, можете передать аргумент -v в команду git commit . Это приведёт к тому, что в комментарий будет также помещена дельта/diff изменений, таким образом вы сможете точно увидеть все изменения которые вы совершили.

Есть и другой способ — вы можете набрать свой комментарий к коммиту в командной строке вместе с командой commit указав его после параметра -m , как в следующем примере:

Итак, вы создали свой первый коммит! Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит ( master ), какая контрольная сумма SHA-1 у этого коммита ( 463dc4f ), сколько файлов было изменено, а также статистику по добавленным/удалённым строкам в этом коммите.

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

Игнорирование индексации

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

Обратите внимание, что в данном случае перед коммитом вам не нужно выполнять git add для файла CONTRIBUTING.md , потому что флаг -a включает все файлы. Это удобно, но будьте осторожны: флаг -a может включить в коммит нежелательные изменения.

Удаление файлов

Затем, если вы выполните команду git rm , удаление файла попадёт в индекс:

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

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

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

Обратите внимание на обратный слеш ( \ ) перед * . Он необходим из-за того, что Git использует свой собственный обработчик имён файлов вдобавок к обработчику вашего командного интерпретатора. Эта команда удаляет все файлы, имеющие расширение .log и находящиеся в каталоге log/ . Или же вы можете сделать вот так:

Эта команда удаляет все файлы, имена которых заканчиваются на ~ .

Перемещение файлов

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

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

и это отлично сработает. На самом деле, если вы выполните что-то вроде этого и посмотрите на статус, вы увидите, что Git считает, что произошло переименование файла:

Однако, это эквивалентно выполнению следующих команд:

Git неявно определяет, что произошло переименование, поэтому неважно, переименуете вы файл так или используя команду mv . Единственное отличие состоит лишь в том, что mv — одна команда вместо трёх — это функция для удобства. Важнее другое — вы можете использовать любой удобный способ для переименования файла, а затем воспользоваться командами add/rm перед коммитом.

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