Как использовать git в командной строке windows

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

1.4 Введение — Командная строка

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

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

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

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

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

30 основных команд, которые сделают из вас мастера Git

  1. Как задать имя пользователя и адрес электронной почты
  2. Кэширование учётных данных
  3. Инициализация репозитория
  4. Добавление отдельных файлов или всех файлов в область подготовленных файлов
  5. Проверка статуса репозитория
  6. Внесение изменений однострочным сообщением или через редактор
  7. Просмотр истории коммитов с изменениями
  8. Просмотр заданного коммита
  9. Просмотр изменений до коммита
  10. Удаление отслеживаемых файлов из текущего рабочего дерева
  11. Переименование файлов
  12. Отмена подготовленных и неподготовленных изменений
  13. Изменение последнего коммита
  14. Откат последнего коммита
  15. Откат заданного коммита
  16. Создание новой ветки и переход в неё
  17. Просмотр списка веток
  18. Удаление ветки
  19. Слияние двух веток
  20. Отображение журнала фиксации в виде графика для текущей или всех веток
  21. Прекращение слияния при конфликте
  22. Добавление удалённого репозитория
  23. Просмотр удалённых URL-адресов
  24. Получение дополнительных сведений об удалённом репозитории
  25. Отправка изменений в удалённый репозиторий
  26. Получение изменений из удалённого репозитория
  27. Слияние удалённого репозитория с локальным
  28. Отправка новой ветки в удалённый репозиторий
  29. Удаление удалённой ветки
  30. Использование перебазирования

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

Имя пользователя нужно, чтобы привязывать коммиты к вашему имени. Это не то же самое, что имя пользователя учётной записи GitHub, с помощью которого выполняется вход в профиль на GitHub. Задать или изменить имя пользователя можно с помощью команды git config. Новое имя будет автоматически отображаться в последующих коммитах, отправленных на GitHub через командную строку. Если хотите скрыть своё реальное имя, можно использовать в качестве имени пользователя Git произвольный набор символов.

git config --global user.name "Tara Routray"

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

git config --global user.email "dev@tararoutray.com"

2. Кэширование учётных данных

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

git config --global credential.helper cache

3. Инициализация репозитория

Создать пустой репозиторий Git или вновь инициализировать существующий можно параметром init. При инициализации он создаст скрытую папку. В ней содержатся все объекты и ссылки, которые Git использует и создаёт в истории работы над проектом.

git init

4. Добавление отдельных файлов или всех файлов в область подготовленных файлов

Добавить отдельный файл в область подготовленных файлов можно параметром add с указанием имени файла. Просто замените somefile.js на актуальное имя.

git add somefile.js

Кроме того, можно добавить все файлы и папки в эту область, предоставив wildcard . вместо имени файла:

git add .

5. Проверка статуса репозитория

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

git status

6. Внесение изменений однострочным сообщением или через редактор

При создании коммита в репозитории можно добавить однострочное сообщение с помощью параметра commit с флагом -m. Само сообщение вводится непосредственно после флага, в кавычках.

git commit -m "Your short summary about the commit"

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

git commit

7. Просмотр истории коммитов с изменениями

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

git log -p

8. Просмотр заданного коммита

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

git show 1af17e73721dbe0c40011b82ed4bb1a7dbe3ce29

Также можно использовать сокращённый хеш.

git show 1af17e

9. Просмотр изменений до коммита

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

git diff

Для просмотра подготовленных изменений необходимо добавить флаг --staged.

git diff --staged

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

git diff somefile.js

10. Удаление отслеживаемых файлов из текущего рабочего дерева

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

git rm dirname/somefile.js

Можно также использовать маски файлов (например *.js) для удаления всех файлов, соответствующих критерию.

git rm dirname/*.html

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

Переименовать файл или папку можно параметром mv. Для него указывается источник source и назначение destination. Источник — реально существующий файл или папка, а назначение — существующая папка.

git mv dir1/somefile.js dir2

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

12. Отмена подготовленных и неподготовленных изменений

Восстановить файлы рабочего дерева, не подготовленные к коммиту, можно параметром checkout. Для проведения операции требуется указать путь к файлу. Если путь не указан, параметр git checkout изменит указатель HEAD, чтобы задать указанную ветку как текущую.

git checkout somefile.js

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

git reset HEAD somefile.js

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

git reset HEAD

13. Изменение последнего коммита

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

git commit --amend -m "Updated message for the previous commit"

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

git add dir1
git commit

# Here you forgot to add dir2 to commit, you can execute the
following command to amend the other files and folders.

git add dir2
git commit --amend --no-edit

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

Внимание! Не изменяйте публичные коммиты.

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

14. Откат последнего коммита

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

git revert HEAD

▍ Разница между revert и reset

Команда git revert отменяет изменения, записанные только одним коммитом. Она не откатывает проект к более раннему состоянию, удаляя все последующие коммиты, как это делает команда git reset.

У команды revert есть два крупных преимущества по сравнению с reset. Во-первых, она не меняет историю проекта и производит операцию, безопасную для коммитов. Во-вторых, её объектом выступает конкретный коммит, созданный в любой момент истории, а git reset всегда берёт за точку отсчёта текущий коммит. К примеру, если нужно отменить старый коммит с помощью git reset, придётся удалить все коммиты, поданные после целевого, а затем выполнить их повторно. Следовательно, команда git revert — гораздо более удобный и безопасный способ отмены изменений.

15. Откат заданного коммита

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

git revert 1af17e

16. Создание новой ветки и переход в неё

Создать новую ветку можно с помощью параметра branch, указав имя ветки.

git branch new_branch_name

Но Git не переключится на неё автоматически. Для автоматического перехода нужно добавить флаг -b и параметр checkout.

git checkout -b new_branch_name

17. Просмотр списка веток

Можно просматривать полный список веток, используя параметр branch. Команда отобразит все ветки, отметит текущую звёздочкой (*) и выделит её цветом.

git branch

Также можно вывести список удалённых веток с помощью флага -a.

git branch -a

18. Удаление ветки

Удалить ветку можно параметром branch с добавлением флага -d и указанием имени ветки. Если вы завершили работу над веткой и объединили её с основной, можно её удалить без потери истории. Однако, если выполнить команду удаления до слияния — в результате появится сообщение об ошибке. Этот защитный механизм предотвращает потерю доступа к файлам.

git branch -d existing_branch_name

Для принудительного удаления ветки используется флаг -D с заглавной буквой. В этом случае ветка будет удалена независимо от текущего статуса, без предупреждений.

git branch -D existing_branch_name

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

git push origin --delete existing_branch_name

19. Слияние двух веток

Объединить две ветки можно параметром merge с указанием имени ветки. Команда объединит указанную ветку с основной.

git merge existing_branch_name

Если надо выполнить коммит слияния, выполните команду git merge с флагом --no-ff.

git merge --no-ff existing_branch_name

Указанная команда объединит заданную ветку с основной и произведёт коммит слияния. Это необходимо для фиксации всех слияний в вашем репозитории.

20. Отображение журнала фиксации в виде графика для текущей или всех веток

Просмотреть историю коммитов в виде графика для текущей ветки можно с помощью параметра log и флагов --graph --oneline --decorate. Опция --graph выведет график в формате ASCII, отражающий структуру ветвления истории коммитов. В связке с флагами --oneline и --decorate, этот флаг упрощает понимание того, к какой ветке относится каждый коммит.

git log --graph --oneline --decorate

Для просмотра истории коммитов по всем веткам используется флаг --all.

git log --all --graph --oneline --decorate

21. Прекращение слияния при конфликте

Прервать слияние в случае конфликта можно параметром merge с флагом --abort. Он позволяет остановить процесс слияния и вернуть состояние, с которого этот процесс был начат.

git merge --abort

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

git reset

22. Добавление удалённого репозитория

Добавить удалённый репозиторий можно параметром remote add, указав shortname и url требуемого репозитория.

git remote add awesomeapp https://github.com/someurl..

23. Просмотр удалённых URL-адресов

Просматривать удалённые URL-адреса можно параметром remote с флагом -v. Этот параметр отображает удалённые подключения к другим репозиториям.

git remote -v

Такая команда открывает доступ к интерфейсу управления удалёнными записями, которые хранятся в файле .git/config репозитория.

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

Получить подробные сведения об удалённом репозитории можно с помощью параметра remote show с указанием имени репозитория — например, origin.

git remote show origin

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

25. Отправка изменений в удалённый репозиторий

Отправлять изменения в удалённый репозиторий можно параметром push с указанием имени репозитория и ветки.

git push origin main

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

26. Получение изменений из удалённого репозитория

Для загрузки изменений из удалённого репозитория используется параметр pull. Он скачивает копию текущей ветки с указанного удалённого репозитория и объединяет её с локальной копией.

git pull

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

git pull --verbose

27. Слияние удалённого репозитория с локальным

Слияние удалённого репозитория с локальным выполняется параметром merge с указанием имени удалённого репозитория.

git merge origin

28. Отправка новой ветки в удалённый репозиторий

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

git push -u origin new_branch

29. Удаление удалённой ветки

Чтобы избавиться от удалённой ветки, используйте параметр push с флагом --delete, указав имя удалённого репозитория и имя ветки.

git push --delete origin existing_branch

30. Использование перебазирования

Для доступа к этой функции используйте параметр rebase с указанием имени ветки. Перебазирование — это процесс объединения или перемещения последовательности коммитов на новый родительский снимок.

git rebase branch_name

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

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

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

Задача: форкнуть репозиторий в GitHub, создать ветку и работать с кодом.

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


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

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

Git — самая популярная система контроля версий. С Git можно работать через командную строку (или терминал). В каждой системе своя встроенная программа для работы с командной строкой. В Windows это PowerShell или cmd, а в Linux или macOS — Terminal.

Вместо встроенных программ можно использовать любую другую — например, Git Bash в Windows или iTerm2 для macOS.

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

Но давайте по порядку — установим Git на компьютер.

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

Windows. Скачайте Git для Windows, запустите exe-файл, следуйте инструкциям.

macOS. Скачайте Git для macOS и запустите dmg-файл. Если он не запускается, зайдите в Системные настройки — Безопасность и нажмите кнопку Open anyway (Всё равно открыть).

Linux. Установите Git через встроенный менеджер пакетов. Если у вас Ubuntu, используйте команду sudo apt-get install git. Команды для других дистрибутивов можно посмотреть здесь.

Как проверить, что Git установился

Откройте терминал и введите команду

Если Git установлен, то вы увидите номер версии, например, 2.35.1.

➜  ~ git --version
git version 2.35.1
➜  ~

Настраиваем Git

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

Добавить имя (введите его внутри кавычек):

git config --global user.name "ваше имя"

Добавить электронную почту (замените email@example. com на вашу почту):

git config --global user.email email@example.com

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

Регистрируемся на GitHub

GitHub (или Гитхаб) — веб-сервис на основе Git, который помогает совместно разрабатывать IT-проекты. На Гитхабе разработчики публикуют свой и редактируют чужой код, комментируют проекты и следят за новостями других пользователей.

Профиль на Гитхабе и все проекты в нём — ваше публичное портфолио разработчика, поэтому нужно завести профиль, если у вас его ещё нет.

  1. Зайдите на сайт https://github. com и нажмите кнопку Sign up.
  2. Введите имя пользователя (понадобится в дальнейшей работе), адрес электронной почты (такой же, как при настройке Git) и пароль.
  3. На почту придёт код активации — введите на сайте.
  4. Появится окно с выбором тарифного плана. Если вы пользуетесь Гитхабом для учёбы, то укажите, что профиль нужен только для вас и вы студент.
  5. Опросы и выбор интересов можно пропустить.

На этом всё — вы зарегистрировались и у вас есть собственный профиль.

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

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

SSH — протокол для безопасного соединения между компьютерами.

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

Мы будем подключаться к GitHub по SSH. Это работает так:

  1. Вы отправляете какую-то информацию на GitHub, который знает ваш открытый ключ.
  2. GitHub по открытому ключу понимает, что вы это вы, и отправляет что-то в ответ.
  3. Только вы можете расшифровать этот ответ, потому что только у вас есть подходящий закрытый ключ.

А чтобы подключиться к GitHub с помощью SSH-ключа, сначала нужно его создать.

Проверяем SSH-ключи

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

Если у вас уже есть SSH-ключ, то в списке будут файлы с именами вроде id_rsa.pub, id_ecdsa.pub или id_ed25519.pub. А если терминал ругается, что директории ~/.ssh не существует, значит, у вас нет SSH-ключей. Давайте это исправим.

Создаём новый SSH-ключ

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

ssh-keygen -t ed25519 -C "your_email@example.com"

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

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Терминал спросит, куда сохранить ключ. Если не хотите менять имя файла, которое предлагает терминал, просто нажмите Enter.

> Generating public/private имя-ключа key pair.
> Enter a file in which to save the key (/c/Users/ваш-профиль/.ssh/id_имя-ключа):*[Press enter]*

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

В результате создаётся новый SSH-ключ, привязанный к вашей электронной почте.

Создание ключа по шагам:

ssh-explained.png

Добавляем SSH-ключ в ssh-agent

ssh-agent — программа для хранения и управления SSH-ключами. Давайте запустим её и добавим туда наш SSH-ключ. Запускаем командой eval "$(ssh-agent -s)":

Если в ответ терминал покажет надпись «Agent pid» и число — значит, всё ок, агент запущен.

Теперь добавим наш ключ командой.

ssh-add ~/.ssh/id_ed25519

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

Теперь, если всё хорошо, появится надпись Identity added — значит, можно переходить к добавлению ключа на GitHub.

Копируем SSH-ключ

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

clip < ~/.ssh/id_ed25519.pub

Команда clip может не сработать на вашем компьютере, тогда есть два способа узнать ключ — простой и сложный.

Сложный способ. Найдите скрытую папку .ssh, откройте файл id_ed25519.pub в текстовом редакторе и скопируйте его содержимое.

Простой способ. Введите команду ниже и ключ появится прямо в терминале — его нужно вручную скопировать в буфер обмена. Ключ начинается с ssh-ed22519 или ssh-rsa (или похожей строки) — поэтому копируйте строку прямо с самого начала.

~ cat ~/.ssh/id_ed25519.pub

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO63MT6VCFuZtCLhLj1J6I7dgEU2BsRdIsnvnr4ax+Fr shklyar@htmlacademy.ru

Не копируйте этот ключ из статьи — он уже не работает.

Добавляем SSH-ключ на GitHub

Это нужно сделать, чтобы GitHub вас узнавал.

Перейдите на страницу для работы с ключами в вашем профиле на GitHub и нажмите кнопку New SSH key.

github_addnew.png

В поле Title нужно добавить название нового ключа. Например, если вы используете Mac, вы можете назвать ключ MacBook Air, или, если ключ для курсов Академии, то Academy. А ключ, который вы скопировали на прошлом шаге, вставьте в поле Key.

ssh-add-github.png

Не копируйте ключ со скриншота — он уже не работает.

Теперь нажмите кнопку Add SSH key и, если потребуется, введите свой пароль от GitHub, чтобы подтвердить сохранение. Если всё сделано верно, новый ключ появится в списке на странице https://github. com/settings/keys.

github-added-key.png

Теперь мы можем поработать с проектом в репозитории.

Что такое репозиторий

Репозиторий — папка с файлами вашего проекта на сервере GitHub. Так вы можете работать с проектом откуда угодно, не переживая, что какие-то файлы потеряются — все данные останутся в репозитории.

Если над проектом работает несколько программистов, сначала создаётся мастер-репозиторий — это общий репозиторий с рабочей версией проекта. А каждый программист работает с форком — то есть полной копией мастер-репозитория. В форке вы можете безнаказанно менять код и не бояться что-то сломать в основной версии проекта.

Делаем форк мастер-репозитория

Заходим в нужный репозиторий и нажимаем на «вилку» с надписью fork.

fork.png

Появится окно Create a new fork — проверьте, что он называется так, как вам нужно, и жмите кнопку Create fork. Через пару секунд всё готово.

fork-details.png

Клонируем форк на компьютер — git clone

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

Открываем терминал и переходим в папку с будущим проектом — для этого используем команду cd your-project. Если вы хотите, чтобы проект лежал в папке device, введите

Если такой папки на компьютере нет, то сначала введите md your-project, чтобы создать эту папку, а затем cd your-project. Подробнее о командах.

Когда перейдёте в папку, введите команду git clone для клонирования репозитория:

git clone git@github.com:your-nickname/your-project.git

Замените your-nickname на ваше имя пользователя на GitHub, а your-project — на название проекта. Проще всего их найти прямо наверху страницы репозитория.

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

➜  device git clone git@github.com:academy-student/1173761-device-34.git
Клонирование в «1173761-device-34»…
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 0), reused 15 (delta 0), pack-reused 0
Получение объектов: 100% (15/15), 145.07 КиБ | 900.00 КиБ/с, готово.

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

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

git clone git@github.com:_your-nickname_/_your-project_.git folder_name

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

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

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

Создаём новую ветку — git branch

Откройте терминал и введите команду

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

git checkout -b имя-новой-ветки.
➜  1173761-device-34 git:(master) git checkout -b task1
Переключено на новую ветку «task1»
➜  1173761-device-34 git:(task1)

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

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

git branch -m старое-имя-ветки новое-имя-ветки.

Сохраняем изменения — git add

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

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

git-status.png

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

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

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

Делаем коммит — git commit

Сделать коммит — значит зафиксировать все сохранённые изменения и дать им название. Это делается с помощью команды commit

git commit -m "ваше сообщение"

Текст сообщения должен быть лаконичным и вместе с этим сообщать о том, что делает коммит (внесённые изменения). Например,

  • Добавляет имя наставника в Readme
  • Вводит функцию сортировки изображений
  • Правит ошибку в поиске городов на карте

git-commit.png

Отправляем изменения на GitHub — git push

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

git push origin название-текущей-ветки

Где origin означает репозиторий на компьютере, то есть ваш форк. Слово origin — часть команды, не меняйте это название на своё.

git-push-origin.png

Создаём пулреквест

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

Если к коду нет вопросов, пулреквест принимается. Если нужно что-то исправить — отклоняется, и придётся исправить код и снова пройти цепочку git addgit commitgit push. Если вы и дальше работаете в той же ветке, а пулреквест ещё не принят, все ваши изменения автоматически добавятся в пулреквест, созданный из этой ветки после команды git push origin название-текущей-ветки.

Чтобы создать пулреквест, зайдите на страницу вашего форка на GitHub. Вверху появилась плашка Compare & pull request, а ещё можно зайти на вкладку Pull Requests.

pr-offer.png

Нажмите на неё и окажетесь на странице открытия пулреквеста. Проверьте описание и нажмите Create pull request.

pr-stage2.png

Готово, теперь ждём остаётся ждать одобрения пулреквеста или комментариев к нему.

Синхронизируем репозитории

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

pr-closed.png

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

В локальном репозитории переключаемся на ветку master.

Забираем изменения из ветки master мастер-репозитория

git pull git@github.com:academy-student/1173761-device-34.git master

Отправляем изменения уже из своей ветки master в ваш форк на GitHub с помощью команды

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

Словарик

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

Git — самая популярная система контроля версий. С Git можно работать через терминал.

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

GitHub (или Гитхаб) — веб-сервис, основанный на Git, который помогает совместно разрабатывать IT-проекты. На Гитхабе разработчики публикуют свой и редактируют чужой код, комментируют проекты и следят за новостями других пользователей.

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

ssh-agent — программа для хранения и управления SSH-ключами.

Репозиторий — папка с файлами вашего проекта на сервере GitHub или у вас на компьютере.

Мастер-репозиторий  это общий для всей команды репозиторий с рабочей версией проекта.

Форк — полная копия мастер-репозитория, в которой вы можете безопасно работать.

Клонировать форк — скачать его командой git clone, чтобы работать с кодом на своём компьютере.

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

Другие материалы по Git

  • Введение в системы контроля версий
  • Шпаргалка по Git. Решение основных проблем
  • Полезные команды для работы с Git
  • Choose a terminal
  • Confirm Git is installed
  • Configure Git
  • Choose a repository
  • Clone a repository

    • Clone with SSH
    • Clone with HTTPS

      • Clone using a token
    • Convert a local directory into a repository

      • Add a remote
      • View your remote repositories
    • Download the latest changes in the project
  • Branches

    • Create a branch
    • Switch to a branch
    • View differences
    • View the files that have changes
    • Add and commit local changes

      • Stage and commit all changes
    • Send changes to GitLab.com
    • Delete all changes in the branch
    • Unstage all changes that have been added to the staging area
    • Undo most recent commit
    • Merge a branch with default branch
  • Advanced use of Git through the command line
  • Synchronize changes in a forked repository with the upstream

Git is an open-source distributed version control system. GitLab is built
on top of Git.

You can do many Git operations directly in GitLab. However, the command line is required for advanced tasks,
like fixing complex merge conflicts or rolling back commits.

If you’re new to Git and want to learn by working in your own project,
learn how to make your first commit.

For a quick reference of Git commands, download a Git Cheat Sheet.

For more information about the advantages of working with Git and GitLab:

  •  Watch the GitLab Source Code Management Walkthrough video.
  • Learn how GitLab became the backbone of the Worldline development environment.

To help you visualize what you’re doing locally, you can install a
Git GUI app.

Choose a terminal

To execute Git commands on your computer, you must open a terminal (also known as command
prompt, command shell, and command line). Here are some options:

  • For macOS users:
    • Built-in Terminal. Press ⌘ command + space and type terminal.
    • iTerm2. You can integrate it with Zsh and Oh My Zsh for color highlighting and other advanced features.
  • For Windows users:
    • Built-in command line. On the Windows taskbar, select the search icon and type cmd.
    • PowerShell.
    • Git Bash. It is built into Git for Windows.
  • For Linux users:
    • Built-in Linux Terminal.

Confirm Git is installed

You can determine if Git is already installed on your computer by opening a terminal
and running this command:

If Git is installed, the output is:

If your computer doesn’t recognize git as a command, you must install Git.

Configure Git

To start using Git from your computer, you must enter your credentials
to identify yourself as the author of your work. The username and email address
should match the ones you use in GitLab.

  1. In your shell, add your user name:

    git config --global user.name "your_username"
    
  2. Add your email address:

    git config --global user.email "your_email_address@example.com"
    
  3. To check the configuration, run:

    git config --global --list
    

    The --global option tells Git to always use this information for anything you do on your system.
    If you omit --global or use --local, the configuration applies only to the current
    repository.

You can read more on how Git manages configurations in the
Git configuration documentation.

Choose a repository

Before you begin, choose the repository you want to work in. You can use any project you have permission to
access on GitLab.com or any other GitLab instance.

To use the repository in the examples on this page:

  1. Go to https://gitlab.com/gitlab-tests/sample-project/.
  2. In the upper right, select Fork.
  3. Choose a namespace for your fork.

The project becomes available at https://gitlab.com/<your-namespace>/sample-project/.

You can fork any project you have access to.

Clone a repository

When you clone a repository, the files from the remote repository are downloaded to your computer,
and a connection is created.

This connection requires you to add credentials. You can either use SSH or HTTPS. SSH is recommended.

Clone with SSH

Clone with SSH when you want to authenticate only one time.

  1. Authenticate with GitLab by following the instructions in the SSH documentation.
  2. Go to your project’s landing page and select Clone. Copy the URL for Clone with SSH.
  3. Open a terminal and go to the directory where you want to clone the files. Git automatically creates a folder with the repository name and downloads the files there.
  4. Run this command:

    git clone git@gitlab.com:gitlab-tests/sample-project.git
    
  5. To view the files, go to the new directory:

You can also
clone a repository and open it directly in Visual Studio Code.

Clone with HTTPS

Clone with HTTPS when you want to authenticate each time you perform an operation
between your computer and GitLab.

  1. Go to your project’s landing page and select Clone. Copy the URL for Clone with HTTPS.
  2. Open a terminal and go to the directory where you want to clone the files.
  3. Run the following command. Git automatically creates a folder with the repository name and downloads the files there.

    git clone https://gitlab.com/gitlab-tests/sample-project.git
    
  4. GitLab requests your username and password.

    If you have enabled two-factor authentication (2FA) on your account, you cannot use your account password. Instead, you can do one of the following:

    • Clone using a token with read_repository or write_repository permissions.
    • Install Git Credential Manager.

    If you have not enabled 2FA, use your account password.

  5. To view the files, go to the new directory:

Clone using a token

Clone with HTTPS using a token if:

  • You want to use 2FA.
  • You want to have a revocable set of credentials scoped to one or more repositories.

You can use any of these tokens to authenticate when cloning over HTTPS:

  • Personal access tokens.
  • Deploy tokens.
  • Project access tokens.
  • Group access tokens.
git clone https://<username>:<token>@gitlab.example.com/tanuki/awesome_project.git

Convert a local directory into a repository

You can initialize a local folder so Git tracks it as a repository.

  1. Open the terminal in the directory you’d like to convert.
  2. Run this command:

    A .git folder is created in your directory. This folder contains Git
    records and configuration files. You should not edit these files
    directly.

  3. Add the path to your remote repository
    so Git can upload your files into the correct project.

Add a remote

You add a “remote” to tell Git which remote repository in GitLab is tied
to the specific local folder on your computer.
The remote tells Git where to push or pull from.

To add a remote to your local copy:

  1. In GitLab, create a project to hold your files.
  2. Visit this project’s homepage, scroll down to Push an existing folder, and copy the command that starts with git remote add.
  3. On your computer, open the terminal in the directory you’ve initialized, paste the command you copied, and press enter:

    git remote add origin git@gitlab.com:username/projectpath.git
    

After you’ve done that, you can stage your files and upload them to GitLab.

View your remote repositories

To view your remote repositories, type:

The -v flag stands for verbose.

Download the latest changes in the project

To work on an up-to-date copy of the project, you pull to get all the changes made by users
since the last time you cloned or pulled the project. Replace <name-of-branch>
with the name of your default branch
to get the main branch code, or replace it with the branch name of the branch
you are currently working in.

git pull <REMOTE> <name-of-branch>

When you clone a repository, REMOTE is typically origin. This is where the
repository was cloned from, and it indicates the SSH or HTTPS URL of the repository
on the remote server. <name-of-branch> is usually the name of your
default branch, but it may be any
existing branch. You can create additional named remotes and branches as necessary.

You can learn more on how Git manages remote repositories in the
Git Remote documentation.

Branches

A branch is a copy of the files in the repository at the time you create the branch.
You can work in your branch without affecting other branches. When
you’re ready to add your changes to the main codebase, you can merge your branch into
the default branch, for example, main.

Use branches when you:

  • Want to add code to a project but you’re not sure if it works properly.
  • Are collaborating on the project with others, and don’t want your work to get mixed up.

A new branch is often called feature branch to differentiate from the
default branch.

Create a branch

To create a feature branch:

git checkout -b <name-of-branch>

Branch names cannot contain empty spaces and special characters. Use only lowercase letters, numbers,
hyphens (-), and underscores (_).

Switch to a branch

All work in Git is done in a branch.
You can switch between branches to see the state of the files and work in that branch.

To switch to an existing branch:

git checkout <name-of-branch>

For example, to change to the main branch:

View differences

To view the differences between your local unstaged changes and the latest version
that you cloned or pulled:

View the files that have changes

When you add, change, or delete files or folders, Git knows about the changes.
To check which files have been changed:

Add and commit local changes

When you type git status, locally changed files are shown in red. These changes may
be new, modified, or deleted files or folders.

  1. To stage a file for commit:

    git add <file-name OR folder-name>
    
  2. Repeat step 1 for each file or folder you want to add.
    Or, to stage all files in the current directory and subdirectory, type git add ..

  3. Confirm that the files have been added to staging:

    The files should be displayed in green text.

  4. To commit the staged files:

    git commit -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"
    

Stage and commit all changes

As a shortcut, you can add all local changes to staging and commit them with one command:

git commit -a -m "COMMENT TO DESCRIBE THE INTENTION OF THE COMMIT"

Send changes to GitLab.com

To push all local changes to the remote repository:

git push <remote> <name-of-branch>

For example, to push your local commits to the main branch of the origin remote:

Sometimes Git does not allow you to push to a repository. Instead,
you must force an update.

Delete all changes in the branch

To discard all changes to tracked files:

This action removes changes to files, not the files themselves.
Untracked (new) files do not change.

Unstage all changes that have been added to the staging area

To unstage (remove) all files that have not been committed:

Undo most recent commit

To undo the most recent commit:

This action leaves the changed files and folders unstaged in your local repository.

You can learn more about the different ways Git can undo changes in the
Git Undoing Things documentation.

Merge a branch with default branch

When you are ready to add your changes to
the default branch, you merge the feature branch into it:

git checkout <default-branch>
git merge <feature-branch>

In GitLab, you typically use a merge request to merge your changes, instead of using the command line.

To create a merge request from a fork to an upstream repository, see the
forking workflow.

Advanced use of Git through the command line

For an introduction of more advanced Git techniques, see Git rebase, force-push, and merge conflicts.

Synchronize changes in a forked repository with the upstream

To create a copy of a repository in your namespace, you fork it.
Changes made to your copy of the repository are not automatically synchronized with the original.
To keep the project in sync with the original project, you need to pull from the original repository.

You must create a link to the remote repository to pull
changes from the original repository. It is common to call this remote repository the upstream.

You can now use the upstream as a <remote> to pull new updates
from the original repository, and use the origin
to push local changes and create merge requests.

Шпаргалка по консольным командам Git

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

Общее

Git — система контроля версий (файлов). Что-то вроде возможности сохраняться в компьютерных играх (в Git эквивалент игрового сохранения — коммит). Важно: добавление файлов к «сохранению» двухступенчатое: сначала добавляем файл в индекс (git add), потом «сохраняем» (git commit).

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

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

Ключ к пониманию

Ключ к пониманию концепции git — знание о «трех деревьях»:

  • Рабочая директория — файловая система проекта (те файлы, с которыми вы работаете).
  • Индекс — список отслеживаемых git-ом файлов и директорий, промежуточное хранилище изменений (редактирование, удаление отслеживаемых файлов).
  • Директория .git/ — все данные контроля версий этого проекта (вся история разработки: коммиты, ветки, теги и пр.).

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

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

Простейший цикл работ

  • Редактирование, добавление, удаление файлов (собственно, работа).
  • Индексация/добавление файлов в индекс (указание для git какие изменения нужно будет закоммитить).
  • Коммит (фиксация изменений).
  • Возврат к шагу 1 или отход ко сну.

Указатели

  • HEAD — указатель на текущий коммит или на текущую ветку (то есть, в любом случае, на коммит). Указывает на родителя коммита, который будет создан следующим.
  • ORIG_HEAD — указатель на коммит, с которого вы только что переместили HEAD (командой git reset ..., например).
  • Ветка (master, develop etc.) — указатель на коммит. При добавлении коммита, указатель ветки перемещается с родительского коммита на новый.
  • Теги — простые указатели на коммиты. Не перемещаются.

Настройки

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

git config --global user.name "Your Name" # указать имя, которым будут подписаны коммиты
git config --global user.email "e@w.com"  # указать электропочту, которая будет в описании коммитера

Если вы в Windows:

git config --global core.autocrlf true # включить преобразование окончаний строк из CRLF в LF

Указание неотслеживаемых файлов

Файлы и директории, которые не нужно включать в репозиторий, указываются в файле .gitignore. Обычно это устанавливаемые зависимости (node_modules/, bower_components/), готовая сборка build/ или dist/ и подобные, создаваемые при установке или запуске. Каждый файл или директория указываются с новой строки, возможно использование шаблонов.

Консоль

Как использовать консоль Bash в Windows, основные команды.

Длинный вывод в консоли: Vim

Вызов некоторых консольных команд приводит к необходимости очень длинного вывода в консоль (пример: вывод истории всех изменений в файле командой git log -p fileName.txt). При этом прямо в консоли запускается редактор Vim. Он работает в нескольких режимах, из которых Вас заинтересуют режим вставки (редактирование текста) и нормальный (командный) режим. Чтобы попасть из Vim обратно в консоль, нужно в командном режиме ввести :q. Переход в командный режим из любого другого: Esc.

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

Vim (некоторые команды)

# Нажатия кнопок
ESC     — переход в командный режим
i       — переход в режим редактирования текста
ZQ (зажат Shift, поочередное нажатие) — выход без сохранения
ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти
```bash
# Нажатия кнопок
ESC     — переход в командный режим
i       — переход в режим редактирования текста
ZQ (зажат Shift, поочередное нажатие) — выход без сохранения
ZZ (зажат Shift, поочередное нажатие) — сохранить и выйти

# Ввод в командном режиме
:q!             — выйти без сохранения
:wq             — сохранить файл и выйти
:w filename.txt — сохранить файл как filename.txt

Консольные команды

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

git init             # создать новый проект в текущей директории
git init folder-name # создать новый проект в указанной директории

Клонирование репозитория

# клонировать удаленный репозиторий в одноименную директорию
git clone https://github.com/cyberspacedk/Git-commands.git    

# клонировать удаленный репозиторий в директорию «FolderName»
git clone https://github.com/cyberspacedk/Git-commands.git FolderName 

# клонировать репозиторий в текущую директорию
git clone https://github.com:nicothin/web-design.git .           

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

git status              # показать состояние репозитория (отслеживаемые, изменённые, новые файлы и пр.)
git diff                # сравнить рабочую директорию и индекс (неотслеживаемые файлы ИГНОРИРУЮТСЯ)
git diff --color-words  # сравнить рабочую директорию и индекс, показать отличия в словах (неотслеживаемые файлы ИГНОРИРУЮТСЯ)
git diff index.html     # сравнить файл из рабочей директории и индекс
git diff HEAD           # сравнить рабочую директорию и коммит, на который указывает HEAD (неотслеживаемые файлы ИГНОРИРУЮТСЯ)
git diff --staged       # сравнить индекс и коммит с HEAD
git diff master feature # посмотреть что сделано в ветке feature по сравнению с веткой master
git diff --name-only master feature # посмотреть что сделано в ветке feature по сравнению с веткой master, показать только имена файлов
git diff master...feature # посмотреть что сделано в ветке feature с момента (коммита) расхождения с master

Добавление изменений в индекс

git add .        # добавить в индекс все новые, изменённые, удалённые файлы из текущей директории и её поддиректорий
git add text.txt # добавить в индекс указанный файл (был изменён, был удалён или это новый файл)
git add -i       # запустить интерактивную оболочку для добавления в индекс только выбранных файлов
git add -p       # показать новые/изменённые файлы по очереди с указанием их изменений и вопросом об отслеживании/индексировании

Удаление изменений из индекса

git reset            # убрать из индекса все добавленные в него изменения (в рабочей директории все изменения сохранятся), антипод git add
git reset readme.txt # убрать из индекса изменения указанного файла (в рабочей директории изменения сохранятся)

Отмена изменений

git checkout text.txt      # ОПАСНО: отменить изменения в файле, вернуть состояние файла, имеющееся в индексе
git reset --hard           # ОПАСНО: отменить изменения; вернуть то, что в коммите, на который указывает HEAD (незакомиченные изменения удалены из индекса и из рабочей директории, неотслеживаемые файлы останутся на месте)
git clean -df              # удалить неотслеживаемые файлы и директории

Коммиты

git commit -m "Name of commit"    # зафиксировать в коммите проиндексированные изменения (закоммитить), добавить сообщение
git commit -a -m "Name of commit" # проиндексировать отслеживаемые файлы (ТОЛЬКО отслеживаемые, но НЕ новые файлы) и закоммитить, добавить сообщение

Отмена коммитов и перемещение по истории

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

git revert HEAD --no-edit    # создать новый коммит, отменяющий изменения последнего коммита без запуска редактора сообщения
git revert b9533bb --no-edit # то же, но отменяются изменения, внесённые коммитом с указанным хешем (b9533bb)

Все команды, приведённые ниже можно выполнять ТОЛЬКО если коммиты еще не были отправлены в удалённый репозиторий.

# ВНИМАНИЕ! Опасные команды, можно потерять незакоммиченные изменения
git commit --amend -m "Название"  # «перекоммитить» изменения последнего коммита, заменить его новым коммитом с другим сообщением (сдвинуть текущую ветку на один коммит назад, сохранив рабочую директорию и индекс «как есть», создать новый коммит с данными из «отменяемого» коммита, но новым сообщением)
git reset --hard @~      # передвинуть HEAD (и ветку) на предыдущий коммит, рабочую директорию и индекс сделать такими, какими они были в момент предыдущего коммита
git reset --hard 75e2d51 # передвинуть HEAD (и ветку) на коммит с указанным хешем, рабочую директорию и индекс сделать такими, какими они были в момент указанного коммита
git reset --soft @~      # передвинуть HEAD (и ветку) на предыдущий коммит, но в рабочей директории и индексе оставить все изменения
git reset --soft @~2     # то же, но передвинуть HEAD (и ветку) на 2 коммита назад
git reset @~             # передвинуть HEAD (и ветку) на предыдущий коммит, рабочую директорию оставить как есть, индекс сделать таким, каким он был в момент предыдущего коммита (удобнее, чем git reset --soft @~, если индекс нужно задать заново)
# Почти как git reset --hard, но безопаснее: не получится потерять изменения в рабочей директории
git reset --keep @~      # передвинуть HEAD (и ветку) на предыдущий коммит, сбросить индекс, но в рабочей директории оставить изменения, если возможно (если файл с изменениями между коммитами менялся, будет выдана ошибка и переключение не произойдёт)

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

git checkout b9533bb # переключиться на коммит с указанным хешем (переместить HEAD на указанный коммит, рабочую директорию вернуть к состоянию, на момент этого коммита)
git checkout master  # переключиться на коммит, на который указывает master (переместить HEAD на коммит, на который указывает master, рабочую директорию вернуть к состоянию на момент этого коммита)

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

Потребуется создание новой ветки, начинающейся с указанного коммита.

git checkout -b new-branch 5589877   # создать ветку new-branch, начинающуюся с коммита c хешем 5589877 (переместить HEAD на указанный коммит, рабочую директорию вернуть к состоянию, на момент этого коммита, создать указатель на этот коммит (ветку) с указанным именем)

Восстановление изменений

git checkout 5589877 index.html  # восстановить в рабочей директории указанный файл на момент указанного коммита (и добавить это изменение в индекс) (git reset index.html для удаления из индекса, но сохранения изменений в файле)

Копирование коммита (перенос коммитов)

git cherry-pick 5589877          # скопировать на активную ветку изменения из указанного коммита, закоммитить эти изменения
git cherry-pick master~2..master # скопировать на активную ветку изменения из master (2 последних коммита)
git cherry-pick -n 5589877       # скопировать на активную ветку изменения из указанного коммита, но НЕ КОММИТИТЬ (подразумевается, что мы сами потом закоммитим)
git cherry-pick master..feature  # скопировать на активную ветку изменения из всех коммитов ветки feature с момента её расхождения с master (похоже на слияние веток, но это копирование изменений, а не слияние), закоммитить эти изменения; это может вызвать конфликт
git cherry-pick --abort    # прервать конфликтный перенос коммитов
git cherry-pick --continue # продолжить конфликтный перенос коммитов (сработает только после решения конфликта)

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

git rm text.txt    # удалить отслеживаемый неизменённый файл и проиндексировать это изменение
git rm -f text.txt # удалить отслеживаемый изменённый файл и проиндексировать это изменение
git rm -r log/     # удалить всё содержимое отслеживаемой директории log/ и проиндексировать это изменение
git rm ind*        # удалить все отслеживаемые файлы с именем, начинающимся на «ind» в текущей директории и проиндексировать это изменение
git rm --cached readme.txt # удалить из отслеживаемых индексированный файл (ФАЙЛ ОСТАНЕТСЯ НА МЕСТЕ) (часто используется для нечаянно добавленных в отслеживаемые файлов)

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

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

git mv text.txt test_new.txt # переименовать файл «text.txt» в «test_new.txt» и проиндексировать это изменение
git mv readme_new.md folder/ # переместить файл readme_new.md в директорию folder/ (должна существовать) и проиндексировать это изменение

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

Выход из длинного лога вывода: q.

git log master             # показать коммиты в указанной ветке
git log -2                 # показать последние 2 коммита в активной ветке
git log -2 --stat          # показать последние 2 коммита и статистику внесенных ими изменений
git log -p -22             # показать последние 22 коммита и внесенную ими разницу на уровне строк
git log --graph -10        # показать последние 10 коммитов с ASCII-представлением ветвления
git log --since=2.weeks    # показать коммиты за последние 2 недели
git log --after '2018-06-30' # показать коммиты, сделанные после указанной даты
git log index.html         # показать историю изменений файла index.html (только коммиты)
git log -5 index.html      # показать историю изменений файла index.html, последние 5 коммитов (только коммиты)
git log -p index.html      # показать историю изменений файла index.html (коммиты и изменения)
git log -G'myFunction' -p  # показать все коммиты, в которых менялись строки с myFunction (в кавычках регулярное выражение)
git log -L '/<head>/','/</head>/':index.html # показать изменения от указанного до указанного регулярных выражений в указанном файле
git log --grep fix         # показать коммиты, в описании которых есть буквосочетание fix (регистрозависимо, только коммиты текущей ветки)
git log --grep fix -i      # показать коммиты, в описании которых есть буквосочетание fix (регистроНЕзависимо, только коммиты текущей ветки)
git log --grep 'fix(ing|me)' -P # показать коммиты, в описании которых есть совпадения для регулярного выражения (только коммиты текущей ветки)
git log --pretty=format:"%h - %an, %ar : %s" -4 # показать последние 4 коммита с форматированием выводимых данных
git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short # мой формат вывода, висящий на алиасе оболочки
git log master..branch_99  # показать коммиты из ветки branch_99, которые не влиты в master
git log branch_99..master  # показать коммиты из ветки master, которые не влиты в branch_99
git log master...branch_99 --boundary -- graph # показать коммиты из указанных веток, начиная с их расхождения (коммит расхождения будет показан)
git show 60d6582           # показать изменения из коммита с указанным хешем
git show HEAD~             # показать данные о предыдущем коммите в активной ветке
git show @~                # аналогично предыдущему
git show HEAD~3            # показать данные о коммите, который был 3 коммита назад
git show my_branch~2       # показать данные о коммите, который был 2 коммита назад в указанной ветке
git show @~:index.html     # показать контент указанного файла на момент предыдущего (от HEAD) коммита
git show :/"подвал"        # показать самый новый коммит, в описании которого есть указанное слово (из любой ветки)

Кто написал строку

git blame README.md --date=short -L 5,8 # показать строки 5-8 указанного файла и коммиты, в которых строки были добавлены

История изменений указателей (веток, HEAD)

git reflog -20             # показать последние 20 изменений положения указателя HEAD
git reflog --format='%C(auto)%h %<|(20)%gd %C(blue)%cr%C(reset) %gs (%s)' -20 # то же, но с указанием давности действий

Ветки

git branch                 # показать список веток
git branch -v              # показать список веток и последний коммит в каждой
git branch new_branch      # создать новую ветку с указанным именем на текущем коммите
git branch new_branch 5589877 # создать новую ветку с указанным именем на указанном коммите
git branch -f master 5589877  # переместить ветку master на указанный коммит
git branch -f master master~2 # переместить ветку master на 2 коммита назад
git checkout new_branch    # перейти в указанную ветку
git checkout -b new_branch # создать новую ветку с указанным именем и перейти в неё
git checkout -B master 5589877 # переместить ветку с указанным именем на указанный коммит и перейти в неё
git merge hotfix           # влить в ветку, в которой находимся, данные из ветки hotfix
git merge hotfix -m "Горячая правка" # влить в ветку, в которой находимся, данные из ветки hotfix (указано сообщение коммита слияния)
git merge hotfix --log     # влить в ветку, в которой находимся, данные из ветки hotfix, показать редактор описания коммита, добавить в него сообщения вливаемых коммитов
git merge hotfix --no-ff   # влить в ветку, в которой находимся, данные из ветки hotfix, запретить простой сдвиг указателя, изменения из hotfix «останутся» в ней, а в активной ветке появится только коммит слияния
git branch -d hotfix       # удалить ветку hotfix (используется, если её изменения уже влиты в главную ветку)
git branch --merged        # показать ветки, уже слитые с активной
git branch --no-merged     # показать ветки, не слитые с активной
git branch -a              # показать все имеющиеся ветки (в т.ч. на удаленных репозиториях)
git branch -m old_branch_name new_branch_name # переименовать локально ветку old_branch_name в new_branch_name
git branch -m new_branch_name # переименовать локально ТЕКУЩУЮ ветку в new_branch_name
git push origin :old_branch_name new_branch_name # применить переименование в удаленном репозитории
git branch --unset-upstream # завершить процесс переименования

Теги

git tag v1.0.0               # создать тег с указанным именем на коммите, на который указывает HEAD
git tag -a -m 'В продакшен!' v1.0.1 master # создать тег с описанием на том коммите, на который смотрит ветка master
git tag -d v1.0.0            # удалить тег с указанным именем(ами)
git tag -n                   # показать все теги, и по 1 строке сообщения коммитов, на которые они указывают
git tag -n -l 'v1.*'         # показать все теги, которые начинаются с 'v1.*'

Временное сохранение изменений без коммита

git stash     # временно сохранить незакоммиченные изменения и убрать их из рабочей директории
git stash pop # вернуть сохраненные командой git stash изменения в рабочую директорию

Удалённые репозитории

Есть два распространённых способа привязать удалённый репозиторий к локальному: по HTTPS и по SSH. Если SSH у вас не настроен (или вы не знаете что это), привязывайте удалённый репозиторий по HTTPS (адрес привязываемого репозитория должен начинаться с https://).

git remote -v              # показать список удалённых репозиториев, связанных с локальным
git branch -r              # показать удаленные ветки
git branch -a              # показать все ветки(локальные и удаленные)       
git remote remove origin   # убрать привязку удалённого репозитория с сокр. именем origin
git remote add origin https://github.com:nicothin/test.git # добавить удалённый репозиторий (с сокр. именем origin) с указанным URL
git remote rm origin       # удалить привязку удалённого репозитория
git remote show origin     # получить данные об удалённом репозитории с сокращенным именем origin
git fetch origin           # скачать все ветки с удаленного репозитория (с сокр. именем origin), но не сливать со своими ветками
git fetch origin master    # то же, но скачивается только указанная ветка
git checkout --track origin/github_branch # создать локальную ветку github_branch (данные взять из удалённого репозитория с сокр. именем origin, ветка github_branch) и переключиться на неё
git push origin master     # отправить в удалённый репозиторий (с сокр. именем origin) данные своей ветки master
git pull origin            # влить изменения с удалённого репозитория (все ветки)
git pull origin master     # влить изменения с удалённого репозитория (только указанная ветка)

Конфликт слияния

Предполагается ситуация: есть ветка master и есть ветка feature. В обеих ветках есть коммиты, сделанные после расхождения веток. В ветку master пытаемся влить ветку feature (git merge feature), получаем конфликт, т.к. в обеих ветках есть изменения одной и той же строки в файле index.html.

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

git merge feature                # влить в активную ветку изменения из ветки feature
git merge-base master feature    # показать хеш последнего общего коммита для двух указанных веток
git checkout --ours index.html   # оставить в конфликтном файле (index.html) состояние ветки, В КОТОРУЮ мы вливаем (в примере — из ветки master)
git checkout --theirs index.html # оставить в конфликтном файле (index.html) состояние ветки, ИЗ КОТОРОЙ мы вливаем (в примере — из ветки feature)
git checkout --merge index.html  # показать в конфликтном файле (index.html) сравнение содержимого сливаемых веток (для ручного редактирования)
git checkout --conflict=diff3  --merge index.html # показать в конфликтном файле (index.html) сравнение содержимого сливаемых веток плюс то, что было в месте конфликта в коммите, на котором разошлись сливаемые ветки
git reset --hard  # прекратить это прерванное слияние, вернуть рабочую директорию и индекс как было в момент коммита, на который указывает HEAD, а я пойду немного поплачу
git reset --merge # прекратить это прерванное слияние, но оставить изменения, не закоммиченные до слияния (для случая, когда слияние делается не на чистом статусе)
git reset --abort # то же, что и строкой выше

«Перенос» ветки

Можно «переместить» ответвление какой-либо ветки от основной на произвольный коммит. Это нужно для того, чтобы в «переносимой» ветке появились какие-либо изменения, внесённые в основной ветке (уже после ответвления переносимой).

Нельзя «переносить» ветку, если она уже отправлена на удалённый репозиторий.

git rebase master # перенести все коммиты (создать их копии) активной ветки так, будто активная ветка ответвилась от master на нынешней вершине master (часто вызывает конфликты)
git rebase --onto master feature # перенести коммиты активной ветки на master, начиная с того места, в котором активная ветка отделилась от ветки feature
git rebase --abort # прервать конфликтный rebase, вернуть рабочую директорию и индекс к состоянию до начала rebase
git rebase --continue # продолжить конфликтный rebase (сработает только после разрешения конфликта и индексации такого разрешения)

Как отменить rebase

git reflog feature -2        # смотрим лог перемещений ветки, которой делали rebase (в этом примере — feature), видим последний коммит ПЕРЕД rebase, на него и нужно перенести указатель ветки
git reset --hard feature@{1} # переместить указатель ветки feature на один коммит назад, обновить рабочую директорию и индекс

Разное

git archive -o ./project.zip HEAD # создать архив с файловой структурой проекта по указанному пути (состояние репозитория, соответствующее указателю HEAD)

Примеры

Собираем коллекцию простых и сложных примеров работы.

Начало работы

Создание нового репозитория, первый коммит, привязка удалённого репозитория с gthub.com, отправка изменений в удалённый репозиторий.

# указана последовательность действий:
# создана директория проекта, мы в ней
git init                      # создаём репозиторий в этой директории
touch readme.md               # создаем файл readme.md
git add readme.md             # добавляем файл в индекс
git commit -m "Старт"         # создаем коммит
git remote add origin https://github.com:nicothin/test.git # добавляем предварительно созданный пустой удаленный репозиторий
git push -u origin master     # отправляем данные из локального репозитория в удаленный (в ветку master)

«Внесение изменений» в коммит

Только если коммит ещё не был отправлен в удалённые репозиторий.

# указана последовательность действий:
subl inc/header.html          # редактируем и сохраняем разметку «шапки»
git add inc/header.html       # индексируем измененный файл
git commit -m "Убрал телефон из шапки" # делаем коммит
# ВНИМАНИЕ: коммит пока не был отправлен в удалённый репозиторий
# сознаём, что нужно было еще что-то сделать в этом коммите.
subl inc/header.html          # вносим изменения
git add inc/header.html       # индексируем измененный файл (можно git add .)
git commit --amend -m "«Шапка»: выполнена задача №34" # заново делаем коммит

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

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

# указана последовательность действий:
git checkout -b new-page-header # создадим новую ветку для задачи изменения «шапки» и перейдём в неё
subl inc/header.html            # редактируем разметку «шапки»
git commit -a -m "Новая шапка: смена логотипа" # делаем коммит (работа еще не завершена)
# тут выясняется, что есть баг с контактом в «подвале»
git checkout master             # возвращаемся к ветке master
subl inc/footer.html            # устраняем баг и сохраняем разметку «подвала»
git commit -a -m "Исправление контакта в подвале" # делаем коммит
git push                        # отправляем коммит с быстрым критическим изменением в master в удалённом репозитории
git checkout new-page-header    # переключаемся обратно в ветку new-page-header для продолжения работ над «шапкой»
subl inc/header.html            # редактируем и сохраняем разметку «шапки»
git commit -a -m "Новая шапка: смена навигации" # делаем коммит (работа над «шапкой» завершена)
git checkout master             # переключаемся в ветку master
git merge new-page-header       # вливаем в master изменения из ветки new-page-header
git branch -d new-page-header   # удаляем ветку new_page_header

Работа с ветками, слияние и откат к состоянию до слияния

Была ветка fix, в которой исправляли баг. Исправили, влили fix в master. но тут выяснилось, что это исправление ломает какую-то функциональность, Нужно откатить master к состоянию без слияния (наличие бага менее критично, чем порча функциональности).

# находимся в ветке fix, баг уже «исправлен»
git checkout master            # переключаемся на master
git merge fix                  # вливаем изменения из fix в master
# видим проблему: часть функциональности сломалась
git checkout fix               # переключаемся на fix (пока мы в master, git не даст ее двигать)
git branch -f master ORIG_HEAD # передвигаем ветку master на коммит, указанный в ORIG_HEAD (тот, на который указывала master до вливания fix)

Работа с ветками, конфликт слияния

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

# указана последовательность действий:
git checkout master           # переключаемся на ветку master
git checkout -b branch-1      # создаём ветку branch-1, основанную на ветке master
subl .                        # редактируем и сохраняем файлы
git commit -a -m "Правка 1"   # коммитим
git checkout master           # возвращаемся к ветке master
git checkout -b branch-2      # создаём ветку branch-2, основанную на ветке master
subl .                        # редактируем и сохраняем файлы
git commit -a -m "Правка 2"   # коммитим
git checkout master           # возвращаемся к ветке master
git merge branch-1            # вливаем изменения из ветки branch-1 в текущую ветку (master), удача (автослияние)
git merge branch-2            # вливаем изменения из ветки branch-2 в текущую ветку (master), КОНФЛИКТ автослияния
# Automatic merge failed; fix conflicts and then commit the result.
subl .                        # выбираем в конфликтных файлах те участки, которые нужно оставить, сохраняем
git commit -a -m "Устранение конфликта" # коммитим результат устранения конфликта

Синхронизация репозитория-форка с мастер-репозиторием

Есть некий репозиторий на github.com, он него нами был сделан форк, добавлены какие-то изменения. Оригинальный (мастер-)репозиторий был как-то обновлён. Задача: стянуть с мастер-репозитория изменения (которые там внесены уже после того, как мы его форкнули).

# указана последовательность действий:
git remote add upstream https://github.com:address.git # добавляем удаленный репозиторий: сокр. имя — upstream, URL мастер-репозитория
git fetch upstream            # стягиваем все ветки мастер-репозитория, но пока не сливаем со своими
git checkout master           # переключаемся на ветку master своего репозитория
git merge upstream/master     # вливаем стянутую ветку master удалённого репозитория upstream в свою ветку master

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

ВАЖНО: это сработает только если коммит еще не отправлен в удалённый репозиторий.

# указана последовательность действий:
# сделали изменения, проиндексировали их, закоммитили в master, но ЕЩЁ НЕ ОТПРАВИЛИ (не делали git push)
git checkout -b new-branch    # создаём новую ветку из master
git checkout master           # переключаемся на master
git reset HEAD~ --hard        # сдвигаем указатель (ветку) master на 1 коммит назад
git checkout new-branch       # переключаемся обратно на новую ветку для продолжения работы

Нужно вернуть содержимое файла к состоянию, бывшему в каком-либо коммите (известен хеш коммита)

# указана последовательность действий:
git checkout f26ed88 -- index.html # восстановить в рабочей директории состояние указанного файла на момент указанного коммита, добавить это изменение в индекс
git commit -am "Navigation fixs"   # сделать коммит

При любом действии с github (или другим удалённым сервисом) запрашивается логин и пароль

Речь именно о запросе пары логин + пароль, а не ключевой фразы. Происходит это потому, что git по умолчанию не сохранит пароль для доступа к репозиторию по HTTPS.

Простое решение: указать git кешировать ваш пароль.

.gitattributes

* text=auto

*.html diff=html
*.css  diff=css
*.scss diff=css

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

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

  1. Основы Git
  2. Коммиты
  3. Файловая система
  4. Просмотр изменений
  5. Удалённые репозитории
  6. Работа с ветками
  7. Продвинутое использование

Git — это система контроля версий (VCS), которая позволяет отслеживать и фиксировать изменения в коде: вы можете восстановить код в случае сбоя или откатить до более ранних версий. А ещё это must-have инструмент для взаимодействия нескольких разработчиков на одном проекте. Подробнее об этом в руководстве по командной разработке с Git.

С Git работают через командную строку или инструменты вроде GitHub Desktop. Команды Git принимают вид git <команда> <аргументы>, где аргументом может быть путь к файлу. В команды также включаются опции, которые обозначаются как --<опция>. Забыли, как использовать команду? Откройте руководство с git help <команда>.

Установка Git

Введение в Git всегда начинается с установки: скачайте Git для Windows, macOS или Linux и проверьте версию с помощью git --version.

Настройка конфигурационного файла

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

Вы можете напрямую отредактировать файл .gitconfig в текстовом редакторе или сделать это командой git config --global --edit. Для отдельных полей это git config --global <поле> <значение> — поля user.name и user.email.

Также можно настроить текстовый редактор для написания сообщений коммитов, используя поле core.editor. А вот поле commit.template позволяет указать шаблон, который будет использоваться при каждом коммите. Ещё одно полезное поле — alias, которое привязывает команду к псевдониму. Например, git config --global alias.st "status -s" позволяет использовать git st вместо git status -s

Команда git config --list выведет все поля и их значения из конфигурационного файла.

Создаём Git-репозиторий

Для инициализации нового репозитория .git подойдёт git init или, если хотите скопировать существующий, git clone <адрес репозитория>.

Введение в Git: настройка

Коммиты

Основы работы с Git предполагают понимание коммитов. Команда git commit откроет текстовый редактор для ввода сообщения коммита. Также эта команда принимает несколько аргументов:

  • -m позволяет написать сообщение вместе с командой, не открывая редактор. Например git commit -m "Пофиксил баг";
  • -a переносит все отслеживаемые файлы в область подготовленных файлов и включает их в коммит (позволяет пропустить git add перед коммитом);
  • --amend заменяет последний коммит новым изменённым коммитом, что бывает полезно, если вы неправильно набрали сообщение последнего коммита или забыли включить в него какие-то файлы.

Советы для эффективного введения в Git:

  • Коммитьте как можно чаще.
  • Одно изменение — один коммит: не помещайте все не связанные между собой изменения в один коммит, разделите их, чтобы было проще откатиться.
  • Формат сообщений: заголовок должен быть в повелительном наклонении, меньше 50 символов в длину и должен логически дополнять фразу this commit will ___(this commit will fix bugs — этот коммит исправит баги). Сообщение должно пояснять, почему был сделан коммит, а сам коммит показывает, что изменилось.
  • Если у вас много незначительных изменений, хорошим тоном считается делать небольшие коммиты при разработке, а при добавлении в большой репозиторий объединять их в один коммит.

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

Введение в Git: история коммитов

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

Мы можем ссылаться на коммит либо через его контрольную сумму, либо через его позицию относительно HEAD, например HEAD~4 ссылается на коммит, который находится 4 коммитами ранее HEAD.

Файловая система Git

Введение в Git: файловая система

Git отслеживает файлы в трёх основных разделах:

  • рабочая директория (файловая система вашего компьютера);
  • область подготовленных файлов (staging area, хранит содержание следующего коммита);
  • HEAD (последний коммит в репозитории).

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

Просмотр изменений в файловых системах

Команда git status отображает все файлы, которые различаются между тремя разделами. У файлов есть 4 состояния:

  1. Неотслеживаемый (untracked) — находится в рабочей директории, но нет ни одной версии в HEAD или в области подготовленных файлов (Git не знает о файле).
  2. Изменён (modified) — в рабочей директории есть более новая версия по сравнению с хранящейся в HEAD или в области подготовленных файлов (изменения не находятся в следующем коммите).
  3. Подготовлен (staged) — в рабочей директории и области подготовленных файлов есть более новая версия по сравнению с хранящейся в HEAD (готов к коммиту).
  4. Без изменений — одна версия файла во всех разделах, т. е. в последнем коммите содержится актуальная версия.

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

Мы можем использовать опцию -s для команды git status, чтобы получить более компактный вывод (по строке на файл). Если файл не отслеживается, то будет выведено ??; если он был изменён, то его имя будет красным, а если подготовлен — зелёным.

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

  • git diff — сравнение рабочей директории с областью подготовленных файлов;
  • git diff --staged — сравнение области подготовленных файлов с HEAD.

Если использовать аргумент <файл/папка>, то diff покажет изменения только для указанных файлов/папок, например git diff src/.

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

Команда git add <файл/папка> обновляет область подготовленных файлов версиями файлов/папок из рабочей директории.

Команда git commit обновляет HEAD новым коммитом, который делает снимки файлов в области подготовленных файлов.

Действие команды git reset <коммит> состоит из трёх потенциальных шагов:

  1. Переместить указатель HEAD на <коммит> (например, при откате коммита в рабочей директории и области подготовленных файлов будут более новые версии файлов, чем в HEAD). Также указатель HEAD ветки будет перемещён на этот коммит.
  2. Обновить область подготовленных файлов содержимым коммита. В таком случае только в рабочей директории будут новейшие версии файлов.
  3. Обновить рабочую директорию содержимым области подготовленных файлов. С этим нужно быть осторожнее, поскольку в итоге будут уничтожены изменения файлов.

По умолчанию команда git reset выполняет только шаги 1 и 2, однако её поведение можно изменить с помощью опций --soft (только 1 шаг) и --hard (все шаги).

Если передать путь к файлу/папке, то команда будет выполнена только для них, например git reset --soft HEAD~1 src/.

Команда git checkout HEAD <файл> приводит к тому же результату, что и git reset --hard HEAD <файл> — перезаписывает версию файла в области подготовленных файлов и в рабочей директорией версией из HEAD, то есть отменяет изменения после последнего коммита.

С другой стороны, git checkout <файл> (уже без HEAD) перезаписывает версию файла в рабочей директории версией в области подготовленных файлов, то есть отменяет изменения с момента последней подготовленной версии.

Наконец, git rm <файл> отменяет отслеживание файла и удаляет его из рабочей директории, опция --cached позволит сохранить файл.

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

Зачастую нам не нужно, чтобы Git отслеживал все файлы в репозитории, потому что в их число могут входить:

  • файлы с чувствительной информацией вроде паролей;
  • большие бинарные файлы;
  • файлы сборок, которые генерируются после каждой компиляции;
  • файлы, специфичные для ОС/IDE, например, .DS_Store для macOS или .iml для IntelliJ IDEA — нам нужно, чтобы репозиторий как можно меньше зависел от системы.

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

  • /___ — позволяет избежать рекурсивности — соответствует файлам только в текущей директории;
  • __/ — соответствует всем файлам в указанной директории;
  • *___ — соответствует всем файлам с указанным окончанием;
  • ! — игнорирование файлов, попадающих под указанный шаблон;
  • [__] — соответствует любому символу из указанных в квадратных скобках;
  • ? — соответствует любому символу;
  • /**/ — соответствует вложенным директориям, например a/**/d соответствует a/d, a/b/d, a/b/c/d и т. д.

Мы даже можем использовать шаблоны поиска при указании файла/папки в других командах. Например, git add src/*.css добавит все файлы .css в папке src.

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

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

  • -p показывает изменения в каждом коммите;
  • --stat показывает сокращённую статистику для коммитов, например изменённые файлы и количество добавленных/удалённых строк в каждом их них;
  • -n показывает n последних коммитов;
  • --since=___ и --until=___ позволяет отфильтровать коммиты по промежутку времени, например --since="2019-01-01" покажет коммиты с 1 января 2019 года;
  • --pretty позволяет указать формат логов (например, --pretty=oneline), также можно использовать --pretty=format для большей кастомизации, например --pretty=format:"%h %s";
  • --grep и -S фильтруют коммиты с сообщениями/изменениями кода, которые содержат указанную строку, например, git log -S имя_функции позволяет посмотреть добавление/удаление функции;
  • --no-merges пропускает коммиты со слиянием веток;
  • ветка1..ветка2 позволяет посмотреть, какие коммиты из ветки 2 не находятся в ветке 1 (полезно при слиянии веток). Например, git log master..test покажет, каких коммитов из ветки test нет в master (о ветках поговорим чуть позже).
  • --left-right ветка1...ветка2 показывает коммиты, которые есть либо в ветке 1, либо в ветке 2, но не в обеих; знак < обозначает коммиты из ветка1, а > — из ветка2. Обратите внимание: используется три точки, а не две;
  • -L принимает аргумент начало,конец:файл или :функция:файл и показывает историю изменений переданного набора строк или функции в файле.

Другой полезной командой является git blame <файл>, которая для каждой строки файла показывает автора и контрольную сумму последнего коммита, который изменил эту строку. -L <начало>, <конец> позволяет ограничить эту команду заданными строками. Это можно использовать, например, для выяснения того, какой коммит привёл к определённому багу (чтобы можно было его откатить).

Наконец, есть команда git grep, которая ищет по всем файлам в истории коммитов (а не только в рабочей директории, как grep) по заданному регулярному выражению. Опция -n отображает соответствующий номер строки в файле для каждого совпадения, а --count показывает количество совпадений для каждого файла.

Примечание Не путайте git grep с git log --grep! Первый ищет по файлам среди коммитов, а последний смотрит на сообщения логов.

Удалённые репозитории

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

При использовании команды git clone <url репозитория> мы не только загружаем себе копию репозитория, но и неявно отслеживаем удалённый сервер, который находится по указанному адресу и которому присваивается имя origin.

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

  • git remote add <имя> <url> — добавляет удалённый репозиторий с заданным именем;
  • git remote remove <имя> — удаляет удалённый репозиторий с заданным именем;
  • git remote rename <старое имя> <новое имя> — переименовывает удалённый репозиторий;
  • git remote set-url <имя> <url> — присваивает репозиторию с именем новый адрес;
  • git remote show <имя> — показывает информацию о репозитории.

Следующие команды работают с удалёнными ветками:

  • git fetch <имя> <ветка> — получает данные из ветки заданного репозитория, но не сливает изменения;
  • git pull <имя> <ветка> — сливает данные из ветки заданного репозитория;
  • git push <имя> <ветка> — отправляет изменения в ветку заданного репозитория. Если локальная ветка уже отслеживает удалённую, то можно использовать просто git push или git pull.

Введение в Git: git push и git pull

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

GitHub

GitHub — это платформа, которая хранит Git-репозитории на своих серверах, и основы распределенной системы управления версиями Git подразумевает умение с ней работать. Вы можете хранить свои удалённые репозитории или участвовать в Open Source проектах на GitHub.

Да, есть и другие платформы, но GitHub идеален для введения в Git и дополняет VCS новыми возможностями.

Например, вы можете сделать форк удалённого репозитория, то есть создать свою копию репозитория на севере GitHub. Это полезно в тех случаях, когда у вас нет прав на создание ветки в оригинальном репозитории. Когда вы воспользуетесь командой git clone, ваш локальный репозиторий будет отслеживать удалённый форк как origin, а оригинальный репозиторий как upstream.

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

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

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

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

Введение в Git: ветвление

Команды:

  • git branch <имя ветки> — создаёт новую ветку с HEAD, указывающим на HEAD. Если не передать аргумент <имя ветки>, то команда выведет список всех локальных веток;
  • git checkout <имя ветки> — переключается на эту ветку. Можно передать опцию -b, чтобы создать новую ветку перед переключением;
  • git branch -d <имя ветки> — удаляет ветку.

Локальный и удалённый репозитории могут иметь немало ветвей, поэтому когда вы отслеживаете удалённый репозиторий — отслеживается удалённая ветка (git clone привязывает вашу ветку master к ветке origin/master удалённого репозитория).

Привязка к удалённой ветке:

  • git branch -u <имя удалённого репозитория>/<удалённая ветка> — привязывает текущую ветку к указанной удалённой ветке;
  • git checkout --track <имя удалённого репозитория>/<удалённая ветка> — аналог предыдущей команды;
  • git checkout -b <ветка> <имя удалённого репозитория>/<удалённая ветка> — создаёт новую локальную ветку и начинает отслеживать удалённую;
  • git branch --vv — показывает локальные и отслеживаемые удалённые ветки;
  • git checkout <удалённая ветка> — создаёт локальную ветку с таким же именем, как у удалённой, и начинает её отслеживать.

В общем, git checkout связан с изменением места, на которое указывает HEAD ветки, что похоже на то, как git reset перемещает общий HEAD.

Прятки и чистка

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

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

Однако порой у вас есть незавершённые изменения, которые нельзя фиксировать. В такой ситуации их можно сохранить и «спрятать» с помощью команды git stash. Чтобы вернуть изменения, используйте git stash apply.

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

Слияние

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

Слиние включает в себя создание нового коммита, который основан на общем коммите-предке двух ветвей и указывает на оба HEAD в качестве предыдущих коммитов. Для слияния мы переходим на основную ветку и используем команду git merge <тематическая ветка>.

Введение в Git: Слияние

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

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

 <<<<<<< HEAD:index.html
 Everything above the ==== is the version in master. 
 =======
 Everything below the ==== is the version in the test branch. 
 >>>>>>> test:index.html

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

Слияние

Перемещение

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

Введение в Git: перемещение

Для перемещения используется команда git rebase <основная ветка> <тематическая ветка>, которая воспроизводит изменения тематической ветки на основной; HEAD тематической ветки указывает на последний воспроизведённый коммит.

Перемещение vs. слияние

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

Сценарий:

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

Перемещайте изменения только на вашей приватной локальной ветке — не перемещайте коммиты, от которых зависит ещё кто-то.

Откат коммитов — revert и reset

Похожие дебаты по поводу того, что лучше использовать, возникают, когда вы хотите откатить коммит. Команда git revert <коммит> создаёт новый коммит, отменяющий изменения, но сохраняющий историю, в то время как git reset <коммит> перемещает указатель HEAD, предоставляя более чистую историю (словно бы этого коммита никогда и не было). Важно отметить, что это также означает, что вы больше не сможете вернуться обратно к этим изменениям, например, если вы всё-таки решите, что отмена коммита была лишней. Чище — не значит лучше!

Продвинутое использование

На этом основное введение в Git заканчивается, и начинается более глубокое изучение.

Интерактивная подготовка

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

  • status — показывает для каждого файла краткое описание того, что (не)подготовлено;
  • update — подготавливает отслеживаемые файлы;
  • revert — убрать один или несколько файлов из подготовленной области;
  • add untracked — подготавливает неотслеживаемый файл;
  • patch — подготавливает только часть файла (полезно, когда вы, например, изменили несколько функций, но хотите разбить изменения на несколько коммитов). После выбора файла вам будут показаны его фрагменты и представлены возможные команды: Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?. Можно ввести ?, чтобы узнать, что делает каждая команда;
  • diff — показывает список подготовленных файлов и позволяет посмотреть изменения для каждого из них;
  • quit — выходит из интерактивной консоли;
  • help — показывает краткое описание каждой команды.

Символ * рядом с файлом означает, что команда изменит его статус (подготовлен/неподготовлен в зависимости от того, происходит ли обновление или откат). Если нажать Enter, не введя ничего ни в одном из под-меню команды, то все файлы перейдут в (не)подготовленное состояние. Создание патчей доступно в интерактивной консоли и через команду git add -p.

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

Для большего контроля над историей коммитов локальной ветки можно использовать команду git rebase -i HEAD~n, которая откроет интерактивную консоль для перемещения набора последних n коммитов, перечисленных в порядке от старых к новым (то есть в том порядке, в котором они будут перемещены). Таким образом вы можете «редактировать историю», однако помните, что оригинальные коммиты нельзя изменить, только переместить.

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

Изменение сообщения/разбивка коммитов

Для указания коммита, который вы хотите изменить, используется команда edit. Затем, когда Git будет проводить перемещение, он остановится на этом коммите. После этого вы можете использовать git commit --amend, чтобы изменить сообщение или подготовить забытые файлы. Если вы хотите разделить коммит, после остановки введите git reset HEAD^ (в результате HEAD будет перемещён на один коммит назад и все изменённые в этом коммите файлы перейдут в статус неподготовленных). Затем вы сможете зафиксировать файлы в отдельных коммитах обычным образом.

После завершения редактирования введите git rebase --continue.

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

Иногда вам может потребоваться перезаписать несколько коммитов — в таких случаях можно использовать git filter-branch. Например, чтобы удалить случайно зафиксированный файл, можно ввести git filter-branch --tree-filter 'git rm -f <имя файла>' HEAD. Однако учтите, что при этом вся история перемещается.

Объединение нескольких коммитов

Схема: Объединение нескольких коммитов

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

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

Кроме слияния/перемещения всех коммитов в тематической ветке, вас может интересовать только определённый коммит. Допустим, у вас есть локальная ветка drafts, где вы работаете над несколькими потенциальными статьями, но хотите опубликовать только одну из них. Для этого можно использовать команду git cherry-pick. Чтобы получить определённые коммиты, из которых мы хотим выбирать, можно использовать git log <основная ветка>..<тематическая>.

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

Схема: Переносим отдельный коммит

Закрепите введение в Git информацией о типичных ошибках в данной VCS и способах их решения.

Перевод статьи «The Ultimate Beginner Git Cheatsheet»

В последние годы популярность git демонстрирует взрывной рост. Эта система контроля версий используется различными проектами с открытым исходным кодом.

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

Основы

Git — это набор консольных утилит, которые отслеживают и фиксируют изменения в файлах (чаще всего речь идет об исходном коде программ, но вы можете использовать его для любых файлов на ваш вкус). Изначально Git был создан Линусом Торвальдсом при разработке ядра Linux. Однако инструмент так понравился разработчикам, что в последствии, он получил широкое распространение и его стали использовать в других проектах. С его помощью вы можете сравнивать, анализировать, редактировать, сливать изменения и возвращаться назад к последнему сохранению. Этот процесс называется контролем версий.

Для чего он нужен? Ну во-первых, чтобы отследить изменения, произошедшие с проектом, со временем. Проще говоря, мы можем посмотреть как менялись файлы программы, на всех этапах разработки и при необходимости вернуться назад и что-то отредактировать. Часто бывают ситуации, когда, во вполне себе работающий код, вам нужно внести определенные правки или улучшить какой-то функционал, по желанию заказчика. Однако после внедрения нововведений, вы с ужасом понимаете, что все сломалось. У вас начинается судорожно дергаться глаз, а в воздухе повисает немой вопрос: “Что делать?” Без системы контроля версий, вам надо было бы долго напряженно просматривать код, чтобы понять как было до того, как все перестало работать. С Гитом же, все что нужно сделать — это откатиться на коммит назад.

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

Установка

Установить git на свою машину очень просто:

  • Linux — нужно просто открыть терминал и установить приложение при помощи пакетного менеджера вашего дистрибутива. Для Ubuntu команда будет выглядеть следующим образом:
    sudo apt-get install git
  • Windows — мы рекомендуем git for windows, так как он содержит и клиент с графическим интерфейсом, и эмулятор bash.
  • OS X — проще всего воспользоваться homebrew. После его установки запустите в терминале:
    brew install git

Если вы новичок, клиент с графическим интерфейсом(например GitHub Desktop и Sourcetree) будет полезен, но, тем не менее, знать команды очень важно.

Настройка

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

git config --global user.name "My Name"
git config --global user.email myEmail@example.com

Теперь каждое наше действие будет отмечено именем и почтой. Таким образом, пользователи всегда будут в курсе, кто отвечает за какие изменения — это вносит порядок.
Git хранит весь пакет конфигураций в файле .gitconfig, находящемся в вашем локальном каталоге. Чтобы сделать эти настройки глобальными, то есть применимыми ко всем проектам, необходимо добавить флаг –global. Если вы этого не сделаете, они будут распространяться только на текущий репозиторий.
Для того, чтобы посмотреть все настройки системы, используйте команду:

git config --list

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

git config --global color.ui true
git config --global color.status auto
git config --global color.branch auto

Если вы не до конца настроили систему для работы, в начале своего пути — не беда. Git всегда подскажет разработчику, если тот запутался, например:

  1. Команда git —help — выводит общую документацию по git
  2. Если введем git log —help — он предоставит нам документацию по какой-то определенной команде (в данном случае это — log)
  3. Если вы вдруг сделали опечатку — система подскажет вам нужную команду
  4. После выполнения любой команды — отчитается о том, что вы натворили
  5. Также Гит прогнозирует дальнейшие варианты развития событий и всегда направит разработчика, не знающего, куда двигаться дальше

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

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

Как мы отметили ранее, git хранит свои файлы и историю прямо в папке проекта. Чтобы создать новый репозиторий, нам нужно открыть терминал, зайти в папку нашего проекта и выполнить команду init. Это включит приложение в этой конкретной папке и создаст скрытую директорию .git, где будет храниться история репозитория и настройки.
Создайте на рабочем столе папку под названием git_exercise. Для этого в окне терминала введите:

$ mkdir Desktop/git_exercise/
$ cd Desktop/git_exercise/
$ git init

Командная строка должна вернуть что-то вроде:

Initialized empty Git repository in /home/user/Desktop/git_exercise/.git/

Это значит, что наш репозиторий был успешно создан, но пока что пуст. Теперь создайте текстовый файл под названием hello.txt и сохраните его в директории git_exercise.

Определение состояния

status — это еще одна важнейшая команда, которая показывает информацию о текущем состоянии репозитория: актуальна ли информация на нём, нет ли чего-то нового, что поменялось, и так далее. Запуск git status на нашем свежесозданном репозитории должен выдать:

$ git status
On branch master
Initial commit
Untracked files:
(use "git add ..." to include in what will be committed)
hello.txt

Сообщение говорит о том, что файл hello.txt неотслеживаемый. Это значит, что файл новый и система еще не знает, нужно ли следить за изменениями в файле или его можно просто игнорировать. Для того, чтобы начать отслеживать новый файл, нужно его специальным образом объявить.

Подготовка файлов

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

$ git add hello.txt

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

$ git add -A

Проверим статус снова, на этот раз мы должны получить другой ответ:

$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: hello.txt

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

Фиксация изменений

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

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

git add index.html
git add css/style.css

или вместе — всё сразу:

git add .

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

git reset:
git reset css/style.css

Теперь создадим непосредственно сам коммит

git commit -m 'Add some code'

Флажок -m задаст commit message — комментарий разработчика. Он необходим для описания закоммиченных изменений. И здесь работает золотое правило всех комментариев в коде: «Максимально ясно, просто и содержательно обозначь написанное!»

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

Для просмотра все выполненных фиксаций можно воспользоваться историей коммитов. Она содержит сведения о каждом проведенном коммите проекта. Запросить ее можно при помощи команды:

git log

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

git show hash_commit

Ну а если вдруг нам нужно переделать commit message и внести туда новый комментарий, можно написать следующую конструкцию:

git commit --amend -m 'Новый комментарий'

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

Удаленные репозитории

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

1. Что такое удаленный репозиторий

Репозиторий, хранящийся в облаке, на стороннем сервисе, специально созданном для работы с git имеет ряд преимуществ. Во-первых — это своего рода резервная копия вашего проекта, предоставляющая возможность безболезненной работы в команде. А еще в таком репозитории можно пользоваться дополнительными возможностями хостинга. К примеру -визуализацией истории или возможностью разрабатывать вашу программу непосредственно в веб-интерфейсе.
Клонирование
Клонирование — это когда вы копируете удаленный репозиторий к себе на локальный ПК. Это то, с чего обычно начинается любой проект. При этом вы переносите себе все файлы и папки проекта, а также всю его историю с момента его создания. Чтобы склонировать проект, сперва, необходимо узнать где он расположен и скопировать ссылку на него. В нашем руководстве мы будем использовать адрес https://github.com/tutorialzine/awesome-project, но вам посоветуем, попробовать создать свой репозиторий в GitHub, BitBucket или любом другом сервисе:

git clone https://github.com/tutorialzine/awesome-project

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

git clone https://github.com/tutorialzine/awesome-project new-folder

2. Подключение к удаленному репозиторию

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

# This is only an example. Replace the URI with your own repository address.
$ git remote add origin https://github.com/tutorialzine/awesome-project.git

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

3. Отправка изменений на сервер

Сейчас самое время переслать наш локальный коммит на сервер. Этот процесс происходит каждый раз, когда мы хотим обновить данные в удаленном репозитории.
Команда, предназначенная для этого — push. Она принимает два параметра: имя удаленного репозитория (мы назвали наш origin) и ветку, в которую необходимо внести изменения (master — это ветка по умолчанию для всех репозиториев).

$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 212 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/tutorialzine/awesome-project.git
* [new branch] master -> master

Эта команда немного похожа на git fetch, с той лишь разницей, что при помощи fetch мы импортируем коммиты в локальную ветку, а применив push, мы экспортируем их из локальной в удаленную. Если вам необходимо настроить удаленную ветку используйте git remote. Однако пушить надо осторожно, ведь рассматриваемая команда перезаписывает безвозвратно все изменения. В большинстве случаев, ее используют, чтобы опубликовать выгружаемые локальные изменения в центральный репозиторий. А еще ее применяют для того, чтобы поделиться, внесенными в локальный репозиторий, нововведениями, с коллегами или другими удаленными участниками разработки проекта. Подытожив сказанное, можно назвать git push — командой выгрузки, а git pull и git fetch — командами загрузки или скачивания. После того как вы успешно запушили измененные данные, их необходимо внедрить или интегрировать, при помощи команды слияния git merge.
В зависимости от сервиса, который вы используете, вам может потребоваться аутентифицироваться, чтобы изменения отправились. Если все сделано правильно, то когда вы посмотрите в удаленный репозиторий при помощи браузера, вы увидите файл hello.txt

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

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

$ git pull origin master
From https://github.com/tutorialzine/awesome-project
* branch master -> FETCH_HEAD
Already up-to-date.

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

Как удалить локальный репозиторий

Вам не понравился один из ваших локальных Git-репозиториев и вы хотите стереть его со своей машины. Для этого вам всего лишь надо удалить скрытую папку «.git» в корневом каталоге репозитория. Сделать это можно 3 способами:

  1. Проще всего вручную удалить эту папку «.git» в корневом каталоге «Git Local Warehouse».
  2. Также удалить, не устраивающий вас, репозиторий можно на github. Открываете нужный вам объект и переходите в пункт меню Настройки. Там, прокрутив ползунок вниз, вы попадете в зону опасности, где один из пунктов будет называться «удаление этого хранилища».
  3. Последний метод удаления локального хранилища через командную строку, для этого в терминале необходимо ввести следующую команду:
cd repository-path/
rm -r .git

Ветвление

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

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

1. Создание новой ветки

Основная ветка в каждом репозитории называется master. Чтобы создать еще одну ветку, используем команду branch <name>

$ git branch amazing_new_feature

Это создаст новую ветку, пока что точную копию ветки master.

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

Сейчас, если мы запустим branch, мы увидим две доступные опции:

$ git branch
amazing_new_feature
* master

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

$ git checkout amazing_new_feature

В Git ветка — это отдельная линия разработки. Git checkout позволяет нам переключаться как между удаленными, так и меду локальными ветками. Это один из способов получить доступ к работе коллеги или соавтора, обеспечивающий более высокую продуктивность совместной работы. Однако тут надо помнить, что пока вы не закомитили изменения, вы не сможете переключиться на другую ветку. В такой ситуации нужно либо сделать коммит, либо отложить его, при помощи команды git stash, добавляющей текущие незакоммиченные изменения в стек изменений и сбрасывающей рабочую копию до HEAD’а репозитория.

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

Наша “потрясающая новая фича” будет еще одним текстовым файлом под названием feature.txt. Мы создадим его, добавим и закоммитим:

$ git add feature.txt
$ git commit -m "New feature complete.”

Изменения завершены, теперь мы можем переключиться обратно на ветку master.

$ git checkout master

Теперь, если мы откроем наш проект в файловом менеджере, мы не увидим файла feature.txt, потому что мы переключились обратно на ветку master, в которой такого файла не существует. Чтобы он появился, нужно воспользоваться merge для объединения веток (применения изменений из ветки amazing_new_feature к основной версии проекта).

$ git merge amazing_new_feature

Теперь ветка master актуальна. Ветка amazing_new_feature больше не нужна, и ее можно удалить.

$ git branch -d awesome_new_feature

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

git checkout -b <имя ветки> origin/<имя ветки>

После этого, новая ветка создается на машине автоматически.

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

git branch -d local_branch_name

где флажок -d являющийся опцией команды git branch — это сокращенная версия ключевого слова —delete, предназначенного для удаления ветки, а local_branch_name – название ненужной нам ветки.
Однако тут есть нюанс: удалить текущую ветку, в которую вы, в данный момент просматриваете — нельзя. Если же вы все-таки попытаетесь это сделать, система отругает вас и выдаст ошибку с таким содержанием:

Error: Cannot delete branch local_branch_name checked out at название_директории

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

Дополнительно

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

1. Отслеживание изменений, сделанных в коммитах

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

Вывод git log

$ git log
commit ba25c0ff30e1b2f0259157b42b9f8f5d174d80d7
Author: Tutorialzine
Date: Mon May 30 17:15:28 2016 +0300
New feature complete
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author: Tutorialzine
Date: Mon May 30 16:30:04 2016 +0300
Added content to hello.txt
commit 09bd8cc171d7084e78e4d118a2346b7487dca059
Author: Tutorialzine
Date: Sat May 28 17:52:14 2016 +0300
Initial commit


Как вы можете заметить, идентификаторы довольно длинные, но для работы с ними не обязательно копировать их целиком — первых нескольких символов будет вполне достаточно. Чтобы посмотреть, что нового появилось в коммите, мы можем воспользоваться командой show [commit]
Вывод git show

$ git show b10cc123
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author: Tutorialzine
Date: Mon May 30 16:30:04 2016 +0300
Added content to hello.txt
diff --git a/hello.txt b/hello.txt
index e69de29..b546a21 100644
--- a/hello.txt
+++ b/hello.txt
@@ -0,0 +1 @@
+Nice weather today, isn't it?


Чтобы увидеть разницу между двумя коммитами, используется команда diff (с указанием промежутка между коммитами):
Вывод git diff

$ git diff 09bd8cc..ba25c0ff
diff --git a/feature.txt b/feature.txt
new file mode 100644
index 0000000..e69de29
diff --git a/hello.txt b/hello.txt
index e69de29..b546a21 100644
--- a/hello.txt
+++ b/hello.txt
@@ -0,0 +1 @@
+Nice weather today, isn't it?


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

2. Возвращение файла к предыдущему состоянию

Гит позволяет вернуть выбранный файл к состоянию на момент определенного коммита. Это делается уже знакомой нам командой checkout, которую мы ранее использовали для переключения между ветками. Но она также может быть использована для переключения между коммитами (это довольно распространенная ситуация для Гита — использование одной команды для различных, на первый взгляд, слабо связанных задач).
В следующем примере мы возьмем файл hello.txt и откатим все изменения, совершенные над ним к первому коммиту. Чтобы сделать это, мы подставим в команду идентификатор нужного коммита, а также путь до файла:

$ git checkout 09bd8cc1 hello.txt

3. Исправление коммита

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

$ git revert HEAD

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

$ git revert b10cc123

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

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

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

// Use a for loop to console.log contents.
for(var i=0; i<arr.length; i++) {
console.log(arr[i]);
}

Тим предпочитает forEach:

// Use forEach to console.log contents.
arr.forEach(function(item) {
console.log(item);
});

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

$ git merge tim_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 // Use a for loop to console.log contents. for(var i=0; i<arr.length; i++) { console.log(arr[i]); } ======= // Use forEach to console.log contents. arr.forEach(function(item) { console.log(item); }); >>>>>>> Tim's commit.


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

// Not using for loop or forEach.
// Use Array.toString() to console.log contents.
console.log(arr.toString());

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

$ git add -A
$ git commit -m "Array printing conflict resolved."

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

5. Настройка .gitignore

В большинстве проектов есть файлы или целые директории, в которые мы не хотим (и, скорее всего, не захотим) коммитить. Мы можем удостовериться, что они случайно не попадут в git add -A при помощи файла .gitignore

  1. Создайте вручную файл под названием .gitignore и сохраните его в директорию проекта.
  2. Внутри файла перечислите названия файлов/папок, которые нужно игнорировать, каждый с новой строки.
  3. Файл .gitignore должен быть добавлен, закоммичен и отправлен на сервер, как любой другой файл в проекте.

Вот хорошие примеры файлов, которые нужно игнорировать:

  • Логи
  • Артефакты систем сборки
  • Папки node_modules в проектах node.js
  • Папки, созданные IDE, например, Netbeans или IntelliJ
  • Разнообразные заметки разработчика.

Файл .gitignore, исключающий все перечисленное выше, будет выглядеть так:

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

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

Git bash и git.io

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

  • Git Bash(Bourne Again Shell) — это приложение, являющееся эмулятором командной строки и предоставляющее, операционной системе, некоторые распространенные утилиты bash и собственно саму систему Git. Это терминал, используемый для взаимодействия с персональным компьютером, посредством письменных команд.
  • URL-адреса хранилищ на Гитхабе могут быть довольно длинными, из-за больших имен репозиториев и файлов. Работать с такими ссылками очень не удобно. Поэтому сайт github.io создал git.io — неплохой сервис по преобразованию этих длинных и беспорядочных URL-адресов в более короткие и понятные. Сайт был создан в 2011 году и вплоть до недавнего времени отлично справлялся со своими обязанностями. Однако в начале этого года компания Гитхаб, из-за участившихся попыток хакеров использовать сайт в злонамеренных целях, остановила работу сервиса, а чем известила пользователей в своем блоге. Разработчики популярного ресурса рекомендуют пользоваться другими URL-cutter’ами, пока работа сервиса не будет налажена.

Заключение.

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

  • Официальная документация, включающая книгу и видеоуроки – тут.
  • “Getting git right” – Коллекция руководств и статей от Atlassian – тут.
  • Список клиентов с графическим интерфейсом – тут.
  • Онлайн утилита для генерации .gitignore файлов – тут.

Оригинал статьи доступен на сайте http://tutorialzine.com

Другие статьи по теме

10 полезных Git команд, которые облегчат работу

Шпаргалка по Git, в которой представлены основные команды

Понравилась статья? Поделить с друзьями:
  • Как использовать docker на windows 10
  • Как использовать виджеты на windows 10
  • Как использовать dism для восстановления системного образа windows 10
  • Как использовать cortana на windows 10
  • Как использовать веб камеру на ноутбуке windows 7