Про GIT. Использование

Примеры решения основных задач при работе с GIT репозиторием.

Термины

  • branch — (бранч) ветка репозитория;
  • origin — алиас на удаленный репозиторий;
  • master — алиас на основную ветку (бранч) локального репозитория репозитория;
  • index — снапшот (снимок), временное хранилище изменений, которые затем войдут в коммит;
  • commit — фиксация изменений в индексе;

Настройка GIT

Настройки сохраняются в файле ~/.gitconfig. Для первичной настройки гита, выполните в консоли:

git config --global user.name "Your Name"
git config --global user.email your_name@gmail.com
git config --global core.autocrlf true
git config --global core.safecrlf true
git config --global color.branch auto
git config --global color.diff auto
git config --global color.interactive auto
git config --global color.status auto

Также можем добавить для удобства алиасы в этом же файле конфига ~/.gitconfig:

[alias]
  st = status
  ci = commit
  br = branch
  co = checkout
  df = diff
  lg = log -p

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

Репозитории

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

git remote -v

Инициализация / Клонирование

Инициализировать новый репозиторий в каталоге с проектом:

git init
Изначально в репозитории не будет ни одной ветки. После первого git commit, все изменения войдут в ветку master, если вы не указывали другие опции.

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

git clone ssh://git@123.45.67.89/vendor/progect/ .

Клонировать удаленный репозиторий в заданный каталог my-project:

git clone ssh://git@123.45.67.89/vendor/project my-project

Индексация изменений

Команды add и rm позволяют добавить или исключить файлы из индекса, соответственно.

Добавить указанные файлы, каталоги (рекурсивно) в индекс:

git add index.php
git add path/to/file.php

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

git add .

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

git rm .buildpath .project *.php~

Исключить файлы *.php из папки tmp/smarty/compile/:

git rm tmp/smarty/compile/*.php

Отменить индексацию последних изменений:

git reset
git reset HEAD file.php   # Убрать из индекса file.php

Добавить в индекс только удаленные файлы:

git add -A

Удалить из индекса файл и добавить в игнор. Файл останется в каталоге.

git rm --cached ИМЯ_ФАЙЛА

Коммиты

Коммит — фиксация изменений в репозитории, находящихся в индексе.

Посмотреть действия при коммите (сравнить индекс с кешем):

git diff --cached

Сделать коммит всех измененных файлов (НЕ добавленных) с заданным комментарием:

git commit -a -m "Текст комментария"
Параметр -a позволяет автоматически проиндексировать все изменения в файлах, перед коммитом. Новые файлы при этом индексироваться не будут, удаленные файлы будут учтены.

Добавить изменения в последний коммит. Изменять комментарий обязательно?

git commit --amend
При выполнении этой команды git откроет файл с данными последнего коммита, в котором нужно отредактировать строку с комментарием. Можно добавить просто UPD #1. Если оставить комментарий без изменений — последний коммит не будет обновлен. Сохраняем изменения и выходим из режима редактирования файла. После этого изменения будут добавлены к предыдущему коммиту.

Переключиться на определенный коммит:

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

Синхронизация (Pull, Push, Fetch)

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

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

git push
# то же, что и 
git push origin master

Залить изменения в ветку fetures:

git push origin features

Внести изменения в удаленный репозиторий ветку experimental:

git push experimental:experimental

Забрать изменения

Забрать изменения с удаленного репозитория и слить их с активной веткой:

git pull

Забрать изменения с удаленного репозитория БЕЗ слияния с активной веткой:

git fetch

Ветки (branch)

Посмотреть список всех веток репозитория:

git branch     # локальные ветки
git branch -a  # локальные и удаленные ветки

Создать новую ветку bugfix:

git branch bugfix

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

git branch -m new-name-branch

Переключиться на ветку feature:

git checkout feature

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

git branch -d new-branch

Создать ветку и перейти в нее:

git branch new-branch
git checkout new-branch
// или так
git checkout -b new-branch

Слить изменения из ветки featute в текущую:

git merge featute

Состояние и история изменений

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

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

git status

Показать историю коммитов с комментариями:

git log

Оценка изменений:

git diff

Показать изменения в исходниках последнего коммита:

git show

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

git show <COMMIT TAG>

Показать изменения в последнем коммите. Не показывает тип изменения — модификация, удаление, добавление.

git log -1 --name-only
git log --stat --summary  # детальный лог

История изменений файла (№ коммита, кто, когда, строка, ..):

git blame -L 160,+10 file.ext // показать 10 строк со 160-й строки

Скрыть изменения (изменения вносятся в стек):

git stash

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

git stash show

Очистить стек скрытых изменений:

git stash clear

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

Отменить индексацию последних изменений:

git reset

Удалить из индекса файл и добавить его в игнор. Файл останется в каталоге.

git rm --cached path/to/file.src

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

git show HEAD^:path/to/file > path/to/save/file

Отменить изменения файла до последнего коммита:

git checkout path/to/file.src
Изменения в самих файлах не отменяются. Сбрасывается только индекс изменений (добавление файлов git add перед коммитом)

Отменить последний коммит (изменения сохранятся):

git reset --soft HEAD^

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

git reset --hard HEAD^

Команда rebase позволяет выбрасывать и сливать коммиты.

Выполнив эту команду Вы потеряете историю изменений!

Больше никто и никогда не увидит этот позорный коммит:

git reset --hard HEAD~3 //...вернее, три последних коммита. Никто. Никогда!

Прочие

Залить изменения на сервер:

git commit -m 'initial commit'
git remote add origin git@codebasehq.com:exmedia/croco-webmasters/wm2.git
git push origin master

Рекомендации

  • Не хорошо делать push --force — будут большие проблемы при попытке синхронизации с репозиторием у остальных клиентов. Есть правило — не модифицировать историю комитов, которые доступны публичны.
  • Для удаления коммитов push --force безобиден, если работаешь с ним один;
  • Вместо 40-значного хеша пожно ссылаться на коммиты по имени: HEAD — последний коммит в текущей ветке, HEAD^ — предпоследний, HEAD^^ — пред-предпоследний;
  • push access — разрешение вносить изменения в исходный репозиторий;
  • gitk — утилита для визуализации веток и коммитов;
Соответствие блоков при разборе конфликтов:

<<<<<<< HEAD
мои правки
=======
удаленные обновления
>>>>>>> 13b5514fe52ac9315978d0022598c05ba7e0e03a

Решение проблем

Aborting commit due to empty commit message

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

git commit -a -F /path-to/commit-message/commit-text.txt

Проблема с символами переноса строк

Нужно конвертировать символы переноса каретки. Для конвертации переносов строк можно использовать утилиту dos2unix:

dos2unix find ./src/path/ -type f
Установить утилиту dos2unix можно из пакета tofrodos:

sudo aptitude install tofrodos

И создать симлинки:

sudo ln -s fromdos dos2unix
sudo ln -s todos unix2dos

  core.autocrlf = true  - при получении кода преобразует символы новой строки к \r\n (для Windows), а при коммите в LF;
  core.autocrlf = input - конвертировать символы переноса строки в LF только при коммите;
  core.safecrlf = true  - защитить бинарные файлы от преобразования символа новой строки;
  core.safecrlf = warn  - проводить авто замену с предупреждениями об ошибках в консоли;
  core.eol = lf - приводит символы к \n при получении;

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

При ошибке «fatal: CRLF would be replaced by LF in file» — установите safecrlf в false!

Используйте следующие настройки для Linux:

core.autocrlf = input

core.safecrlf = false