Git ================================================================================ Ссылки ------ * Книга "Pro Git" http://progit.org/book/ * Книга "Git Community Book" http://book.git-scm.com/ * Книга "Git Magic" http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html перевод: http://habrahabr.ru/blogs/Git/80909/ * Сравнение команд Git-SVN http://git.or.cz/course/svn.html * Редактирование истории в git http://gq.net.ru/2009/12/16/git-history-rewrite/ Установка --------- Win: http://code.google.com/p/msysgit/ Надо везде указать UTF-8 Настройка --------- 1. Отредактировать файл ~/.gitconfig [user] name = Maxim Oleinik email = maxim.oleinik@gmail.com [color] diff = auto status = auto branch = auto [alias] st = status ci = commit br = branch co = checkout di = diff plog = log --pretty=format:'%h %Cblue%cn %Creset%cr %Cgreen%s' # можно указать любые свои алиасы к разным командам [core] whitespace = trailing-space, space-before-tab, cr-at-eol Или использовать команду git config: git config --global user.name "Maxim Oleinik" git config --global user.email "maxim.oleinik@gmail.com" !!! Далее все примеры будут использовать указанные алиасы. 2. Чтобы игнорировать конфигурационные файлы личного IDE, которые не не должны фигурировать в .gitignore, надо указать все эти файлы в PROJECT_DIR/.git/info/exclude Общее ----- # Утилита для просмотра дерева коммитов gitk --all & или gitg # Создать репозиторий в текущей директории git init # Клонировать существующий репозиторий git clone /path/to/repo git clone http://github.com/symfony/symfony.git # Игнорирование файлов Перечислить все в PROJECT_DIR/.gitignore # Полностью обновить свой репозиторий git fetch git fetch --tags # Обновить теги, которые были "передвинуты" git remote prune origin # Убрать ссылки на удаленные ветки git co master git merge origin/master git submodule update --init # Обновить ссылки на субмодули git submodule foreach 'git submodule update --init' # Обновить субмодули субмодулей Рабочий процесс --------------- # показать статус - список измененных незакоммиченных файлов git st # Staged - промежуточный коммит git add git add myFile* git add git add . # Добавить ВСЁ в текущей директории git add -p # Добавлять фрагментами дифа, просматривая каждое изменение # ОЧЕНЬ рекомендую использовать постоянно git add -N . # Добавить все "новые" файлы под контроль без содержимого (только путь), # т.е. git покажет содержимое этих файлов в дифе git rm # удалить файл или директорию git ls-files -d | xargs git rm # Если файлы удалили ручками без git rm, # тогда это поможет удалить их для git скопом git mv # переименовать файл # фактически это 2 команды add NEW + rm OLD # Diff git di --cached # просмотреть изменения, которые будут закоммичены (добавлены как git add) git di # просмотреть изменения, которые не "добавлены" git di HEAD # просмотреть все измения git di -b -w # посмотреть диф без учета пробелов # Новые файлы (не добавленные через git add) diff не показывает. # Или можно добавить их через git add -N # Коммит git сi # закоммитить изменения добавленные через git add git сi -a # закоммитить все изменения # новые файлы (не добавленные через git add) не коммитятся git сi - закоммитить указанные файлы (независимо от git add) # Отменить текущие незакоммиченные изменения в файлах git co # откатить не "добавленные" измения git reset HEAD # отменить git add Управление коммитами, откат изменений ------------------------------------- см. http://gq.net.ru/2009/12/16/git-history-rewrite/ git revert HEAD # создаст новый зеркальный коммит git commit --amend # изменить сообщение последнего коммита # Откатить коммит, отредактировать и закоммитить заново git reset --soft HEAD^ # откатить последний коммит ... внести измения git commit # закоммитить # Объединить коммиты, удалить, изменить порядок git rebase -i HEAD~3 # последние 3 коммита # откроется редактор со списком коммитов с командой напротив каждого коммита # там есть справка, какие команды есть, и что они делают Ветки и Теги ------------ # Работа с тегами см. git help tag git tag -f TAG_NAME # Передвинуть существующую метку в новую точку # Ветки git br # список локальных веток git br -r # список веток внешнего репозитория git br -a # список всех веток git br my-branch # создать ветку my-branch с текущей позиции git co -b my-branch master # создать ветку my-branch от master и переключиться на нее git co -b some-branch origin/some-branch # создать ветку some-branch из origin репозитория git br -d my-branch # безопасно удалить ветку (смерджена в текущую) git br -D my-branch # принудительно удалить ветку git co my-branch # переключиться на указанную ветку # Merge A - B - C (master) \ D - E (my-branch) git co master git merge my-branch A - B - C - F (master) \ / D - E (my-branch) # Cherry-pick - положить указанный коммит в текущую ветку A - B - C (master) \ D (my-branch) git co master git cherry-pick D A - B - C - D' (master) \ D (my-branch) # Подтянуть ветку A - B - C (master) \ D - E (my-branch) git co my-branch git rebase master A - B - C (master) \ D - E (my-branch) # Пененести ветку (поменять родителя) A - B - C (master) \ D - E (branch-1) \ F - G (branch-2) git co branch-2 git rebase --onto master branch-1 branch-2 A - B - C (master) \ \ \ F - G (branch-2) \ D - E (branch-1) Работа с удаленным репозиторием ------------------------------- git remote # см. git help remote git fetch # загрузить изменения из внешнего репозитория # в локальный репозиторий изменения не применяются git pull origin master # загрузить в ТЕКУЩУЮ ветку изменения из origin/master # аналог git merge origin/master - и ЛУЧШЕ всего использовать этот вариант # во избежания разных недоразумений, поскольку сразу видно, что будет мердж в текущую ветку git push origin master # отправить свои коммиты из local/master в origin/master git push origin my-branch # экспортировать локальную ветку в my-branch в origin/master git push origin my-branch:remote-branch # отправить правки из локальной ветки my-branch # во внешнюю remote-branch git push origin :remote-branch # удалить ветку `remote-branch` из внешнего репозитория # Удалить у себя все упоминания origin веток, которые кто-то уже удалил git remote prune origin # Теги git push --tags # Отправить теги в удаленный репозиторий git fetch --tags # Принудительно загрузить теги (если были передвинуты) git push origin :TAG_NAME # Удалить метку из удаленного репо Пример командной работы над задачей в отдельной ветке ----------------------------------------------------- # Обновить свой репозиторий git fetch git co master git merge origin/master # Создать ветку "t314-article-form" под текущую задачу и переключиться на нее git co -b t314-article-form # ... работа и коммиты в новой ветке # Пока работал, master уже ушел вперед, надо обновить свою локальную копию master git fetch git co master git merge origin/master # Обратно в ветку и подтянуть ее к мастеру git co t314-article-form git rebase master # Подтянуть ветку к новым правкам, # теперь ветка со всеми коммитами будет начинаться из новой точки # Отправить ветку в общий (origin) репозиторий на ревью git push origin t314-article-form # После ревью слить и удалить ненужную теперь ветку git co master git merge t314-article-form git br -d t314-article-form # Удалить локальную ветку git push origin :t314-article-form # Удалить ветку из общего репозитория # Все участники команды по-прежнему видят удаленную ветку. Удаляют ссылки у себя: git remote prune origin Stash ----- см. git help shash Пример работы над 2 задачами с изпользованием stash # Сохранить текущие незакоммиченные правки, # чтобы переключиться в другую ветку для срочной работы git stash save "Моя незаконченная работа" # ... переключаемся в другую ветку, работаем там и возвращаемся обратно # Восстанавливаем спрятанные правки git stash apply # поднимет последнее сохранение git stash apply stash@{0} # или явно указать номер git stas clear # полностью очистить всю хоронушку или git stash pop # восстановить правки и удалить запись о них # Просмотреть список всех сохраненных состояний git stash list История ------- git show - выводит информацию об объектах (коммитах, метках, деревьях и пр.) --------- git show # показать последний коммит git show fb47ddb2 # показать указанный коммит git show HEAD^ # предыдущий коммит (второй с конца) git show HEAD^^ # третий коммит с конца git show HEAD~4 # пятый коммит с конца -- слияния git show HEAD^1 # show the first parent of HEAD git show HEAD^2 # show the second parent of HEAD ---- git show my-branch:fs/locks.c # посмотреть версию конкретного файла git log - вывести список коммитов по условию ---- git log v2.5.. # commits since (not reachable from) v2.5 git log test..master # commits reachable from master but not test git log master..test # ...reachable from test but not master git log master...test # ...reachable from either test or master, but not both git log origin/master..master # разница с внешним хранилищем - что надо закоммитить git log --since="2 weeks ago" # commits from the last 2 weeks git log Makefile # commits which modify Makefile git log fs/ # ... which modify any file under fs/ git log -S'foo()' # commits which add or remove any file data # matching the string 'foo()' ---- git log --no-merges # Не показывать мерджи git log -n 5 -p --reverse FILE # Посмотреть последние 5 дифов указанного файла еще см. http://book.git-scm.com/3_reviewing_history_-_git_log.html - LOg Субмодули --------- Добавить в проект другой git-репозиторий ввиде субмодуля как внешнюю зависимость. Нельзя добавить только часть репозитория как svn:externals, только весь целиком. см. git help submodule # Добавить субмодуль git submodule add http://github.com/maxim-oleinik/symfony-dev-rules ./doc/rules # Чтобы коммитить в субмодуль, надо изменить конфиг ./doc/rules/.git/config url = git@github.com:/maxim-oleinik/symfony-dev-rules.git # Обновить ссылки на субмодули git submodule update git submodule update --init # Выполнить указанную команду для каждого субмодуля git submodule foreach git submodule foreach 'git st' # Удалить субмодуль 1. Удалить из .gitmodules 2. Удалить из .git/config 3. Удалить файлы git rm --cached path/to/submodule 4. Закоммитить результат # Обновить конфиг проекта, при переключении модуля на другой репозиторий git submodule sync Субмодули в свою очередь могут иметь другие субмодули и так до бесконечности. Это жутко неудобно. И поэтому, лучше явно прописывать все зависимости в одном месте. Прочее ------ # Очистить все файлы и директории, которые не стоят под контролем git clean -fd git clean -fdx # !!! Удалит все файлы перечисленные в .gitignore # Лог всех манипуляций с репозиторием. Здесь можно искать потерянные коммиты git reflog # Оптимизировать и перепаковать репозиторий git gc # Работа с патчами git format-patch HEAD~2 # Создать набор патчей от указанной точки git format-patch master..test git apply /path/to/patch/file # Применить патч git send-email patch_files # Отправить набор патчей по email