##### TOP OF THE FILE ################################################## ##### 1. Посмотреть все установленные настройки и узнать где именно они заданы: $ git config --list --show-origin file:/home/moon/.gitconfig user.name=Leo N. Vlassov file:/home/moon/.gitconfig user.email=vlassov@mail.com file:/home/moon/.gitconfig core.editor=vi ##### 2. Установка параметров для всех $ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com $ git config --global core.editor vi Если для каких-то отдельных проектов вы хотите указать другое имя или электронную почту, можно выполнить эту же команду без параметра --global в каталоге с нужным проектом. ##### 3. Установить имя "main" для вашей ветки по умолчанию: $ git config --global init.defaultBranch main ###################### Создание Git-репозитория ######################## ##### 4. $ cd /usr/home/moon/Desktop/GIT_tests/test_project $git init Initialized empty Git repository in /usr/home/moon/Desktop/GIT_tests/test_project/.git/ $ Проект ещё не находится под версионным контролем. Если вы хотите добавить под версионный контроль существующие файлы (в отличие от пустого каталога), вам стоит добавить их в индекс и осуществить первый коммит изменений. Добиться этого вы сможете запустив команду git add несколько раз, указав индексируемые файлы, а затем выполнив git commit: ##### 5. $ touch first.c second.c LICENSE $ ll total 19 drwxr-xr-x 3 moon wheel uarch 6 Oct 16 14:41 ./ drwxr-xr-x 3 moon wheel uarch 8 Oct 16 14:39 ../ drwxr-xr-x 7 moon wheel uarch 10 Oct 16 14:39 .git/ -rw-r--r-- 1 moon wheel uarch 0 Oct 16 14:41 LICENSE -rw-r--r-- 1 moon wheel uarch 0 Oct 16 14:41 first.c -rw-r--r-- 1 moon wheel uarch 0 Oct 16 14:41 second.c $ git add *.c LICENSE $ git commit -m 'initial project version' [main (root-commit) fe6accb] initial project version 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 LICENSE create mode 100644 first.c create mode 100644 second.c ############## Клонирование (Выкачать проект к себе) ################### ############## существующего репозитория ################### Для получения копии существующего Git-репозитория, например, проекта, в который вы хотите внести свой вклад, необходимо использовать команду git clone. Если вы знакомы с другими системами контроля версий, такими как Subversion, то заметите, что команда называется "clone", а не "checkout". Это важное различие – вместо того, чтобы просто получить рабочую копию, Git получает копию практически всех данных, которые есть на сервере. При выполнении git clone с сервера забирается (pulled) каждая версия каждого файла из истории проекта. ##### 6. HTTPS protocol: --- local name project folder IS THE SAME AS remote name; $ git clone https://github.com/libgit2/libgit2 --- то же, но мой фолдер имеет имя "mylibgit"; $ git clone https://github.com/libgit2/libgit2 mylibgit SSH protocol: git:// или user@server:path/to/repo.git #################### Запись изменений в репозиторий #################### ##### 7. $ git status On branch main nothing to commit, working tree clean $ echo 'My Project' > README $ ll total 28 drwxr-xr-x 3 moon wheel uarch 7 Oct 16 14:55 ./ drwxr-xr-x 3 moon wheel uarch 8 Oct 16 14:50 ../ drwxr-xr-x 8 moon wheel uarch 13 Oct 16 14:55 .git/ -rw-r--r-- 1 moon wheel uarch 0 Oct 16 14:41 LICENSE -rw-r--r-- 1 moon wheel uarch 11 Oct 16 14:55 README -rw-r--r-- 1 moon wheel uarch 0 Oct 16 14:41 first.c -rw-r--r-- 1 moon wheel uarch 0 Oct 16 14:41 second.c $ git status On branch main Untracked files: (use "git add ..." to include in what will be committed) README nothing added to commit but untracked files present (use "git add" to track) ##### 8. $ git add README $ git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) new file: README $ Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет все файлы из указанного каталога в индекс. ##### 9. $ echo 'My Project -- CONTRIB..' > CONTRIBUTING.md $ git add CONTRIBUTING.md $ vi CONTRIBUTING.md My Project -- CONTRIB.. second line =====> My Project -- CONTRIB.. ~ ~ :wq $ git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) new file: CONTRIBUTING.md new file: README Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: CONTRIBUTING.md Отслеживаемый файл был изменён в рабочем каталоге, но пока не проиндексирован. $ git add CONTRIBUTING.md $ git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) new file: CONTRIBUTING.md new file: README $ ТЕПЕРЬ ВСЁ ОК! ##### 10. $ vi CONTRIBUTING.md add line =====> "third line =====> My Project -- CONTRIB.." $ git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) new file: CONTRIBUTING.md new file: README Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: CONTRIBUTING.md Commiting в этом случае - закомитит предыдущую версию CONTRIBUTING.md. Т.е. придётся для CONTRIBUTING.md снова выполнить git add, чтобы проиндексировать последнюю версию файла. $ git add CONTRIBUTING.md $ git status On branch main Changes to be committed: (use "git restore --staged ..." to unstage) new file: CONTRIBUTING.md new file: README Теперь закомитится с последними изменениями. $ git status -s // -s - Give the output in the short-format.; A CONTRIBUTING.md A README ?? LICENSE.txt $ Сокращённый вывод статуса. ?? - новые неотслеживаемые файлы; A - файлы добавленные в отслеживаемые; M - отредактированные файлы помечены. ####################### Игнорирование файлов ########################### ##### 11. В коневой директории проекта: $ touch .gitignore $ vi .gitignore # ignore all .a files *.a # but do track lib.a, even though you're ignoring .a files above !lib.a # only ignore the TODO file in the current directory, not subdir/TODO /TODO # ignore all files in any directory named build build/ # ignore doc/notes.txt, but not doc/server/arch.txt doc/*.txt # ignore all .pdf files in the doc/ directory and any of its subdirectories doc/**/*.pdf ##### 12. ПОСМОТРЕТЬ то, что ещё не проидексировано (стажированно): ...исправленные... $ git diff ...подготовленные для комита... git diff --cached для просмотра проиндексированных изменений (--staged и --cached синонимы): $ git diff --staged diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a7f1747 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +My Project -- CONTRIB.. +second line =====> My Project -- CONTRIB.. +third line =====> My Project -- CONTRIB.. diff --git a/README b/README new file mode 100644 index 0000000..56266d3 --- /dev/null +++ b/README @@ -0,0 +1 @@ +My Project $ ##### 13. * ########################### Коммит изменений ########################### ##### 14. $ git commit // default text-editor will runnig; or $ git commit -m 'comment' $ git commit -m "comment" -m '' ... // concatenated as new articles; ######################## Игнорирование индексации ###################### ##### 15. $ git commit -a // Tell the command to automaticaly stage files that have been modified and deleted, but new files you have not told Git about are not affected. // Заставляет Git автоматически индексировать каждый уже отслеживаемый на момент коммита файл, позволяя вам обойтись без git add. ########################## Удаление файлов ############################# ##### 16. $ rm PROJECTS.md $ git rm PROJECTS.md or ##### 17. $ git rm -f PROJECTS.md // if once have been indexed; or ##### 18. $ git rm --cached README // Оставить файл на жёстком диске, но перестать отслеживать изменения в нём. ##### 19. В команду git rm можно передавать файлы, каталоги или шаблоны. Это означает, что вы можете сделать что-то вроде: $ git rm log/\*.log Обратите внимание на обратный слэш (\) перед *. Он необходим из-за того, что Git использует свой собственный обработчик имён файлов вдобавок к обработчику вашего командного интерпретатора. Эта команда удаляет все файлы имеющие расширение .log находящиеся в директории log/. Или же вы можете сделать вот так: $ git rm \*~ Эта команда удаляет все файлы, имена которых заканчиваются на ~. #################### Перемещение файлов ###################### ##### 20. $ git mv file_from file_to или эквивалент $ mv README.md README $ git rm README.md $ git add README ######################## Просмотр истории коммитов ##################### Скачаем чужой проект себе "simplegit-progit" ##### 21. $ mkdir samplegit $ cd samplegit/ $ git clone https://github.com/schacon/simplegit-progit Cloning into 'simplegit-progit'... remote: Enumerating objects: 13, done. remote: Total 13 (delta 0), reused 0 (delta 0), pack-reused 13 Unpacking objects: 100% (13/13), 1.55 KiB | 317.00 KiB/s, done. $ cd simplegit-progit/ $ ll total 19 drwxr-xr-x 4 moon wheel uarch 6 Oct 16 19:51 ./ drwxr-xr-x 3 moon wheel uarch 3 Oct 16 19:51 ../ drwxr-xr-x 8 moon wheel uarch 13 Oct 16 19:51 .git/ -rw-r--r-- 1 moon wheel uarch 125 Oct 16 19:51 README -rw-r--r-- 1 moon wheel uarch 592 Oct 16 19:51 Rakefile drwxr-xr-x 2 moon wheel uarch 3 Oct 16 19:51 lib/ $ git log commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 first commit ##### 22. Одним из самых полезных аргументов является -p или --patch, который показывает разницу (выводит патч), внесенную в каждый коммит. Так же вы можете ограничить количество записей в выводе команды; используйте параметр -2 для вывода только двух записей: $ git log -p -2 commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "simplegit" - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" s.email = "schacon@gmail.com" s.summary = "A simple gem for using Git in Ruby code." commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -18,8 +18,3 @@ class SimpleGit end end - -if $0 == __FILE__ - git = SimpleGit.new - puts git.show -end \ No newline at end of file (END) ##### 23. Сокращенная статистика для каждого коммита. $ git log --stat commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code lib/simplegit.rb | 5 ----- 1 file changed, 5 deletions(-) commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 first commit README | 6 ++++++ Rakefile | 23 +++++++++++++++++++++++ lib/simplegit.rb | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+) ##### 24. Следующая полезная опция --pretty. Эта опция меняет формат вывода. Опции short, full и fuller делают вывод приблизительно в том же формате, но с меньшим или большим количеством информации соответственно: $ git log --pretty=oneline ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) changed the verison number 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test code a11bef06a3f659402fe7563abf99ad00de2209e6 first commit $ ##### 25. $ git log --pretty=format:"%h - %an, %ar : %s" ca82a6d - Scott Chacon, 13 years ago : changed the verison number 085bb3b - Scott Chacon, 13 years ago : removed unnecessary test code a11bef0 - Scott Chacon, 13 years ago : first commit $ ГДЕ: Table 1. Полезные опции для git log --pretty=format Опция Описания вывода %H -> Хеш коммита %h -> Сокращенный хеш коммита %T -> Хеш дерева %t -> Сокращенный хеш дерева %P -> Хеш родителей %p -> Сокращенный хеш родителей %an -> Имя автора %ae -> Электронная почта автора %ad -> Дата автора (формат даты можно задать опцией --date=option) %ar -> Относительная дата автора %cn -> Имя коммитера %ce -> Электронная почта коммитера %cd -> Дата коммитера %cr -> Относительная дата коммитера %s -> Содержание ##### 26. Опции oneline и format являются особенно полезными с опцией --graph команды log. С этой опцией вы сможете увидеть небольшой граф в формате ASCII, который показывает текущую ветку и историю слияний: $ git log --pretty=format:"%h %s" --graph * 2d3acf9 ignore errors from SIGCHLD on trap * 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit |\ | * 420eac9 Added a method for getting the current branch. * | 30e367c timeout code and tests * | 5a09431 add timeout protection to grit * | e1193f8 support for heads with slashes in them |/ * d6016bc require time for xmlschema * 11d191e Merge branch 'defunkt' into local $ ##### 27. Наиболее распространенные опции для команды git log содержит описание как уже рассмотренных, так и нескольких новых опций, которые могут быть полезными в зависимости от нужного формата вывода. Table 2. Наиболее распространенные опции для команды git log Опция Описание -p ===> Показывает патч для каждого коммита. --stat ===> Показывает статистику измененных файлов для каждого коммита. --shortstat ===> Отображает только строку с количеством изменений/вставок/удалений для команды --stat. --name-only ===> Показывает список измененных файлов после информации о коммите. --name-status ===> Показывает список файлов, которые добавлены/изменены/удалены. --abbrev-commit ===> Показывает только несколько символов SHA-1 чек-суммы вместо всех 40. --relative-date ===> Отображает дату в относительном формате (например, "2 weeks ago") вместо стандартного формата даты. --graph ===> Отображает ASCII граф с ветвлениями и историей слияний. --pretty ===> Показывает коммиты в альтернативном формате. Возможные варианты опций: oneline, short, full, fuller и format (с помощью последней можно указать свой формат). --oneline ===> Сокращение для одновременного использования опций --pretty=oneline --abbrev-commit. ##### 28. Ограничение вывода. Опция -, где n – это любое натуральное число и представляет собой n последних коммитов. ##### 29. Опции для ограничения вывода по времени, такие как --since и --until. Например, следующая команда покажет список коммитов, сделанных за последние две недели: $ git log --since=2.weeks Это команда работает с большим количеством форматов — вы можете указать определенную дату вида "2008-01-15" или же относительную дату, например "2 years 1 day 3 minutes ago". ##### 30. Фильтровать список коммитов по заданным параметрам. Опция --author дает возможность фильтровать по автору коммита, а опция --grep искать по ключевым словам в сообщении коммита. Допускается указывать несколько параметров --author и --grep для поиска, которые позволят найти коммиты, сооветствующие любому указанному --author и любому указанному --grep шаблону; однако, применение опции --all-match заставит искать коммиты соответствующие всем указанным --grep шаблонам. ##### 31. Опция -S, которая принимает аргумент в виде строки и показывает только те коммиты, в которых изменение в коде повлекло за собой добавление или удаление этой строки. Например, если вы хотите найти последний коммит, который добавил или удалил вызов определенной функции, вы можете запустить команду: $ git log -S function_name ##### 32. Опция, которую принимает команда git log как фильтр, является путь. Если вы укажете директорию или имя файла, вы ограничите вывод только теми коммитами, в которых были изменения этих файлов. Эта опция всегда указывается последней после двойного тире (--), что отделяет указываемый путь от опций. ##### 33. Table 3. Опции для ограничения вывода команды git log Опция Описание -(n) Показывает только последние n коммитов. --since, --after Показывает только те коммиты, которые были сделаны после указанной даты. --until, --before Показывает только те коммиты, которые были сделаны до указанной даты. --author Показывает только те коммиты, в которых запись author совпадает с указанной строкой. --committer Показывает только те коммиты, в которых запись committer совпадает с указанной строкой. --grep Показывает только коммиты, сообщение которых содержит указанную строку. -S Показывает только коммиты, в которых изменение в коде повлекло за собой добавление или удаление указанной строки. Например, если вы хотите увидеть, в каких коммитах произошли изменения в тестовых файлах в исходном коде Git в октябре 2008 года, автором которых был Junio Hamano и которые не были комитами слияния, вы можете запустить следующую команду: $ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" --before="2008-11-01" --no-merges -- t/ В зависимости от используемого порядка работы, история коммитов в вашем репозитории может содержать большое количество коммитов слияния, которые сами по себе не очень информативны. Чтобы исключить их из вывода команды git log используйте опцию --no-merges. ############################## Операции отмены ######################### $ git commit --amend Эта команда использует область подготовки (индекс) для внесения правок в уже сделанный (последний) коммит. Если вы ничего не меняли с момента последнего коммита (например, команда запущена сразу после предыдущего коммита), то снимок состояния останется в точности таким же, а всё что вы сможете изменить — это ваше сообщение к коммиту. Запустится тот же редактор, только он уже будет содержать сообщение предыдущего коммита. Вы можете редактировать сообщение как обычно, однако, оно заменит сообщение предыдущего коммита. Например, если вы сделали коммит и поняли, что забыли проиндексировать изменения в файле, который хотели добавить в коммит, то можно сделать следующее: ##### 34. $ git commit -m 'initial commit' ..ой забыл.. $ git add forgotten_file $ git commit --amend В итоге получится единый коммит — второй коммит заменит результаты первого. Очень важно понимать, что когда вы вносите правки в последний коммит, вы не столько исправляете его, сколько заменяете новым, который полностью его перезаписывает. В результате всё выглядит так, будто первоначальный коммит никогда не существовал, а так же он больше не появится в истории вашего репозитория. ######################## Отмена индексации файла ####################### Например, вы изменили два файла и хотите добавить их в разные коммиты, но случайно выполнили команду git add * и добавили в индекс оба. Как исключить из индекса один из них? Команда git status напомнит вам: ##### 35. $ git add . $ git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) renamed: README.md -> README modified: CONTRIBUTING.md Прямо под текстом “Changes to be committed” говорится: используйте git reset HEAD ... для исключения из индекса. Давайте последуем этому совету и отменим индексирование файла CONTRIBUTING.md: $ git reset HEAD CONTRIBUTING.md Unstaged changes after reset: M CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) renamed: README.md -> README Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: CONTRIBUTING.md Команда выглядит несколько странно, но — работает! Файл CONTRIBUTING.md изменен, но больше не добавлен в индекс. Команда git reset может быть опасной если вызвать её с параметром --hard. В приведенном примере файл не был затронут, следовательно команда относительно безопасна. ##################### Отмена изменений в файле ######################### ##### 36. Что делать, если вы поняли, что не хотите сохранять свои изменения файла CONTRIBUTING.md? Как можно просто отменить изменения в нём — вернуть к тому состоянию, которое было в последнем коммите (или к начальному после клонирования, или еще как-то полученному)? Нам повезло, что git status подсказывает и это тоже. В выводе команды из последнего примера список изменений выглядит примерно так: Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: CONTRIBUTING.md Здесь явно сказано как отменить существующие изменения. Давайте так и сделаем: $ git checkout -- CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) renamed: README.md -> README Если вы хотите сохранить изменения в файле, но прямо сейчас их нужно отменить, то есть способы получше, такие как ветвление и пребережение. ################## Работа с удалёнными репозиториями ################### ##### 37. Если Вы клонировали репозиторий, $ git clone https://github.com/schacon/ticgit Cloning into 'ticgit'... remote: Enumerating objects: 1857, done. remote: Total 1857 (delta 0), reused 0 (delta 0), pack-reused 1857 Receiving objects: 100% (1857/1857), 334.06 KiB | 659.00 KiB/s, done. Resolving deltas: 100% (837/837), done. $ git remote -v fatal: not a git repository (or any parent up to mount point /usr) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). $ ll total 18 drwxr-xr-x 3 moon wheel uarch 3 Oct 17 10:56 ./ drwxr-xr-x 5 moon wheel uarch 10 Oct 17 10:56 ../ drwxr-xr-x 8 moon wheel uarch 16 Oct 17 10:56 ticgit/ $ cd ticgit $ git remote -v origin https://github.com/schacon/ticgit (fetch) origin https://github.com/schacon/ticgit (push) $ Если у вас больше одного удалённого репозитория, команда выведет их все, с указанием типов протоколов. ################ Добавление удалённых репозиториев ##################### ##### 38. Добавить удалённый репозиторий и присвоить ему имя (shortname) ===> git remote add : $ git remote origin $ git remote add pb https://github.com/paulboone/ticgit $ git remote -v origin https://github.com/schacon/ticgit (fetch) origin https://github.com/schacon/ticgit (push) pb https://github.com/paulboone/ticgit (fetch) pb https://github.com/paulboone/ticgit (push) Теперь вместо указания полного пути вы можете использовать pb. $ git fetch pb remote: Counting objects: 43, done. remote: Compressing objects: 100% (36/36), done. remote: Total 43 (delta 10), reused 31 (delta 5) Unpacking objects: 100% (43/43), done. From https://github.com/paulboone/ticgit * [new branch] master -> pb/master * [new branch] ticgit -> pb/ticgit . . . P.S. Ветка master из репозитория Пола сейчас доступна вам под именем pb/master. Вы можете слить её с одной из ваших веток или переключить на неё локальную ветку, чтобы просмотреть содержимое ветки Пола. Более подробно работа с ветками рассмотрена в [ch03-git-branching]. ############# Получение изменений из удалённого репозитория — Fetch и Pull ################ ##### 39. Как вы только что узнали, для получения данных из удалённых проектов, следует выполнить: $ git fetch [remote-name] Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. После того как вы выполнили команду, у вас должны появиться ссылки на все ветки из этого удалённого проекта, которые вы можете просмотреть или слить в любой момент. Когда вы клонируете репозиторий, команда clone автоматически добавляет этот удалённый репозиторий под именем “origin”. Таким образом, git fetch origin извлекает все наработки, отправленные на этот сервер после того, как вы его склонировали (или получили изменения с помощью fetch). Важно отметить, что команда git fetch забирает данные в ваш локальный репозиторий, но не сливает их с какими-либо вашими наработками и не модифицирует то, над чем вы работаете в данный момент. Вам необходимо вручную слить эти данные с вашими, когда вы будете готовы. ##### 40. Если у вас есть ветка, настроенная на отслеживание удалённой ветки (обратитесь к главе 3 [ch03-git-branching] за более подробной информацией), то вы можете использовать команду git pull чтобы автоматически получить изменения из удалённой ветки и слить их со своей текущей. TOP OF THE NOTE Начиная с версии 2.27, конманда git pull выдаёт предупреждение, если настройка pull.rebase не установлена. Git будет выводить это предупреждение каждый раз пока настройка не будет установлена. Если хотите использовать поведение Git по умолчанию (простое смещение вперёд если возможно — иначе создание коммита слияния): git config --global pull.rebase "false" Если хотите использоовать перебазирование при получении изменений: git config --global pull.rebase "true" BOTTOM OF THE NOTE ########## Отправка изменений в удаленный репозиторий (Push) ########### ##### 41. git push прим. $ git push origin master Эта команда срабатывает только в случае, если вы клонировали с сервера, на котором у вас есть права на запись, и если никто другой с тех пор не выполнял команду push. Если вы и кто-то ещё одновременно клонируете, затем он выполняет команду push, а после него выполнить команду push попытаетесь вы, то ваш push точно будет отклонён. Вам придётся сначала получить изменения и объединить их с вашими и только после этого вам будет позволено выполнить push. Обратитесь к главе [ch03-git-branching] для более подробного описания, как отправлять изменения на удалённый сервер. ################### Просмотр удаленного репозитория #################### ##### 42. git remote show $ git remote show origin * remote origin Fetch URL: https://github.com/schacon/ticgit Push URL: https://github.com/schacon/ticgit HEAD branch: master Remote branches: master tracked dev-branch tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date) Она выдаёт URL удалённого репозитория, а также информацию об отслеживаемых ветках. Эта команда любезно сообщает вам, что если вы, находясь на ветке master, выполните git pull, ветка master с удалённого сервера будет автоматически влита в вашу сразу после получения всех необходимых данных. Она также выдаёт список всех полученных ею ссылок. #################### Удаление и переименование удалённых репозиториев ##################### ##### 43. Переименовать удалённый репозиторий pb в paul. $ git remote rename pb paul $ git remote origin paul Стоит упомянуть, что это также изменит имена удалённых веток в вашем репозитории. То, к чему вы обращались как pb/master, теперь стало paul/master. ##### 44. Удалить ссылку на удалённый репозиторий paul. $ git remote rm paul $ git remote origin При удалении ссылки на удалённый репозиторий все отслеживаемые ветки и настройки, связанные с этим репозиторием, так же будут удалены. ########################## МЕТКИ (v1.0, и т.п.) ######################## Метки в Git называются ТЕГАМИ. Как и большинство СКВ, Git имеет возможность помечать определённые моменты в истории как важные. Как правило, эта функциональность используется для отметки моментов выпуска версий (v1.0, и т.п.). В этом разделе вы узнаете, как посмотреть имеющиеся теги, создать новые или удалить существующие, а так же какие их типы существуют в Git. ##################### Просмотр списка имеющихся меток ################## git tag (параметры -l и --list по умолчанию, если не используется шаблон) $ git tag v0.1 v1.3 поиск тега по шаблону $ git tag -l 'v1.8.5*' v1.8.5 v1.8.5-rc0 v1.8.5-rc1 v1.8.5-rc2 v1.8.5-rc3 v1.8.5.1 v1.8.5.2 v1.8.5.3 v1.8.5.4 v1.8.5.5 Если вы хотите отфильтровать список тегов согласно шаблону, использование параметров -l или --list становится обязательным. ########################### Создание меток ############################# Метки быват... 1. Аннотированные метки - с ними связана доп. информация. 2. Легковесные метки - просто метка. ###################### Аннотированные метки ############################ Создание аннотированной метки в Git выполняется легко. Самый простой способ — это указать -a при выполнении команды tag: $ git tag -a v1.4 -m 'my version 1.4' $ git tag v0.1 v1.3 v1.4 Опция -m задаёт сообщение, которое будет храниться вместе с тегом. Если не указать сообщение, то Git запустит редактор, чтобы вы смогли его ввести. С помощью команды git show вы можете посмотреть данные тега вместе с коммитом: $ git show v1.4 tag v1.4 Tagger: Ben Straub Date: Sat May 3 20:19:12 2014 -0700 my version 1.4 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number Здесь приведена информация об авторе тега, дате его создания и аннотирующее сообщение перед информацией о коммите. ########################### Легковесные метки ########################## Легковесная метка — это ещё один способ пометить коммит. По сути, это контрольная сумма коммита, сохранённая в файл — больше никакой информации не хранится. Для создания легковесной метки не передавайте опций -a, -s и -m, укажите только название: $ git tag v1.4-lw $ git tag v0.1 v1.3 v1.4 v1.4-lw v1.5 На этот раз при выполнении git show для этого тега вы не увидите дополнительной информации. Команда просто покажет коммит: $ git show v1.4-lw commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number ################ Отложенная расстановка меток ##################### Также возможно помечать уже пройденные коммиты. Предположим, история коммитов выглядит следующим образом: $ git log --pretty=oneline 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support 0d52aaab4479697da7686c15f77a3d64d9165190 one more thing 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment' 0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function 4682c3261057305bdd616e23b64b0857d832627b added a todo file 166ae0c4d3f420721acbb115cc33848dfcc2121a started write support 9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile 964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo 8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme Теперь предположим, что вы забыли отметить версию проекта v1.2, которая была там, где находится коммит “updated rakefile”. Вы можете добавить метку и позже. Для отметки коммита укажите его контрольную сумму (или её часть) как параметр команды: $ git tag -a v1.2 9fceb02 Проверим, что коммит отмечен: $ git tag v0.1 v1.2 v1.3 v1.4 v1.4-lw v1.5 $ git show v1.2 tag v1.2 Tagger: Scott Chacon Date: Mon Feb 9 15:32:16 2009 -0800 version 1.2 commit 9fceb02d0ae598e95dc970b74767f19372d61af8 Author: Magnus Chacon Date: Sun Apr 27 20:43:35 2008 -0700 updated rakefile ... ##################### Метками --> на удалённый сервер ################## По умолчанию, команда git push не отправляет теги на удалённые сервера. После создания теги нужно отправлять явно на удалённый сервер. Процесс аналогичен отправке веток — достаточно выполнить команду git push origin . $ git push origin v1.5 Counting objects: 14, done. Delta compression using up to 8 threads. Compressing objects: 100% (12/12), done. Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done. Total 14 (delta 3), reused 0 (delta 0) To git@github.com:schacon/simplegit.git * [new tag] v1.5 -> v1.5 Если у вас много тегов, и вам хотелось бы отправить все за один раз, то можно использовать опцию --tags для команды git push. В таком случае все ваши теги отправятся на удалённый сервер (если только их уже ещё нет). $ git push origin --tags Counting objects: 1, done. Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To git@github.com:schacon/simplegit.git * [new tag] v1.4 -> v1.4 * [new tag] v1.4-lw -> v1.4-lw Теперь, если кто-то склонирует (clone) или выполнит git pull из вашего репозитория, то он получит вдобавок к остальному и ваши метки. TOP OF THE NOTE: git push отправляет оба типа тегов Отправка тегов командой git push --tags не различает аннотированные и легковесные теги; не существует простой опции, которая позволила бы вам указать тип тегов для отправки. BOTTOM OF THE NOTE ############################# Удаление меток ########################### Для удаления тега в локальном репозитории достаточно выполнить команду git tag -d . Например, удалить созданный ранее легковесный тег можно следующим образом: $ git tag -d v1.4-lw Deleted tag 'v1.4-lw' (was e7d5add) Обратите внимание, что при удалении тега не происходит его удаление с сервера. Распространены два способа удаление тега из удалённого репозитория. Первый способ — это выполнить команду git push :refs/tags/: $ git push origin :refs/tags/v1.4-lw To /git@github.com:schacon/simplegit.git - [deleted] v1.4-lw Это следует понимать как обновление удаленного тэга пустым значением, что при водит к его удалению. Второй способ удалить тег из удалённого репозитория более интуитивный: $ git push origin --delete ########################## Переход на метку ############################ Если вы хотите получить версии файлов, на которые указывает тег, то вы можете сделать git checkout для тега. Однако, это переведёт репозиторий в состояние “detached HEAD”, которое имеет ряд неприятных побочных эффектов. $ git checkout v2.0.0 Note: checking out 'v2.0.0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b HEAD is now at 99ada87... Merge pull request #89 from schacon/appendix-final $ git checkout 2.0-beta-0.1 Previous HEAD position was 99ada87... Merge pull request #89 from schacon/appendix-final HEAD is now at df3f601... add atlas.json and cover image Если в состоянии “detached HEAD” внести изменения и сделать коммит, то тег не изменится, при этом новый коммит не будет относиться ни к какой из веток, а доступ к нему можно будет получить только по его хэшу. Поэтому, если вам нужно внести изменения — исправить ошибку в одной из старых версий — скорее всего вам следует создать ветку: $ git checkout -b version2 v2.0.0 Switched to a new branch 'version2' Если сделать коммит в ветке version2, то она сдвинется вперед и будет отличаться от тега v2.0.0, так что будте с этим осторожны. ############################# Псевдонимы в Git ######################### Псевдонимы (aliases) --- команд и да же строк. Прежде, чем закончить эту главу по основам Git, рассмотрим ещё одну маленькую хитрость, которая поможет сделать использование Git проще, легче, и более привычным: псевдонимы (aliases). Мы не будем ссылаться на них дальше или предполагать, что вы будете пользоваться ими по ходу чтения книги, но вам лучше было бы знать, как их использовать. Git не будет пытаться сделать вывод о том, какую команду вы хотели ввести, если вы ввели её неполностью. Если вы не хотите печатать каждую команду для Git целиком, вы легко можете настроить псевдонимы (alias) для любой команды с помощью git config. Вот несколько примеров псевдонимов, которые вы, возможно, захотите задать: $ git config --global alias.co checkout $ git config --global alias.br branch $ git config --global alias.ci commit $ git config --global alias.st status Это означает, что, например, вместо ввода git commit, вам достаточно набрать только git ci. По мере освоения Git вам, вероятно, придётся часто пользоваться и другими командами. В этом случае без колебаний создавайте новые псевдонимы. Такой способ может также быть полезен для создания команд, которые, как вы думаете, должны существовать. Например, чтобы исправить неудобство, с которым мы столкнулись при исключении файла из индекса, можно добавить в Git свой собственный псевдоним unstage: $ git config --global alias.unstage 'reset HEAD --' Это делает эквивалентными следующие две команды: $ git unstage fileA $ git reset HEAD -- fileA Такой вариант кажется немного более понятным. Также, обычно, добавляют команду last следующим образом: $ git config --global alias.last 'log -1 HEAD' Таким образом, можно легко просмотреть последний коммит: $ git last commit 66938dae3329c7aebe598c2246a8e6af90d04646 Author: Josh Goebel Date: Tue Aug 26 19:48:51 2008 +0800 test for current head Signed-off-by: Scott Chacon Можно сказать, что Git просто заменяет эти команды на созданные вами псевдонимы (alias). Однако, возможно, вы захотите выполнить внешнюю команду, а не подкоманду Git. В этом случае, следует начать команду с символа !. Это полезно, если вы пишете свои утилиты для работы с Git-репозиторием. Продемонстрируем этот случай на примере создания псевдонима git visual для запуска gitk: $ git config --global alias.visual "!gitk" ######################################################################## ####### ####### ####### ##### ##### #### ## ## #### ## ## ##### #### ####### ####### ## ## ## ## ## ## ### ## ## ## ## ## ## ## ####### ####### ##### ##### ###### ## ### ## ###### #### #### ####### ####### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ####### ####### ##### ## ## ## ## ## ## #### ## ## ##### #### ####### ####### ####### ######################################################################## $ git log --oneline --decorate --graph --all ####################### Ветвление в Git ################################ Создать ВЕТКУ -- создать новою ссылку на GIT-данные -- при создании - указывает на текущее локальное отслеживаемое сосотояние проекта. В дальнейшем (при выполнении команды commit) "ветки" расходятся. Посмотреть список веток можно с пом. ком.: $ git branch --PARAMS WHERE: -r, --remotes List or delete (if used with -d) the remote-tracking branches. Combine with --list to match the optional pattern(s). -a, --all List both remote-tracking branches and local branches. Combine with --list to match optional pattern(s). -l, --list List branches. With optional ..., e.g. git branch --list 'maint-*', list only the branches that match the pattern(s). --show-current Print the name of the current branch. In detached HEAD state, nothing is printed. -v, -vv, --verbose When in list mode, show sha1 and commit subject line for each head, along with relationship to upstream branch (if any). If given twice, print the path of the linked worktree (if any) and the name of the upstream branch, as well (see also git remote show ). Note that the current worktree’s HEAD will not have its path printed (it will always be your current directory). ######################## Создание новой ветки ########################## Создать новую ветку с именем "testing" от существующей "master". $ git branch testing OR $$ git branch -b testing // создать и пепреключиться; Команда `git log` покажет вам куда указывают указатели веток. Опция --decorate. $ git log --oneline --decorate f30ab (HEAD, master, testing) add feature #32 - ability to add new 34ac2 fixed bug #1328 - stack overflow under certain conditions 98ca9 initial commit of my project Здесь можно увидеть указывающие на коммит f30ab ветки: master и testing. ######################## Переключение веток ############################ "HEAD" - это указатель на текущую ветку (в SVN это не так). Для переключения на существующую ветку "testing" выполните команду git checkout: $ git checkout testing OR $ git switch testing В результате указатель HEAD переместится на ветку с именем "testing". Какой в этом смысл? Давайте сделаем ещё один коммит: EDIT какой то FILE test.rb, потом: $ git commit -a -m 'made a change' Указатель на ветку "testing" переместился вперёд, а "master" указывает на тот же коммит, где вы были до переключения веток командой git checkout. Давайте переключимся назад на ветку master: $ git checkout master Теперь указатель HEAD ушёл назад на ветку "master" и файлы в рабочем каталоге вернулись в то состояние, на снимок которого указывает "master". Это также означает, что все вносимые с этого момента изменения будут относиться к старой версии проекта. Другими словами, вы откатили все изменения ветки "testing" и можете продолжать в другом направлении. !!!!!! Переключение веток меняет файлы в рабочем каталоге !!!!! __ Сделаем еще несколько изменений и создадим очередной коммит: $ vi test.rb $ git commit -a -m 'made other changes' Теперь история вашего проекта разошлась (разветвилась). Вы создали ветку и переключились на нее, поработали, а затем вернулись в основную ветку и поработали в ней. Эти изменения изолированы друг от друга: вы можете свободно переключаться туда и обратно, а когда понадобится — объединить их. И все это делается простыми командами: branch, checkout и commit. __ Все описанные действия можно визуализировать с помощью команды git log. Для отображения истории коммитов, текущего положения указателей веток и истории ветвления выполните команду git log --oneline --decorate --graph --all. $ git log --oneline --decorate --graph --all * c2b9e (HEAD, master) made other changes | * 87ab2 (testing) made a change |/ * f30ab add feature #32 - ability to add new formats to the * 34ac2 fixed bug #1328 - stack overflow under certain conditions * 98ca9 initial commit of my project ПОЯСНЕНИЕ Ветка в Git — это простой файл, содержащий 40 символов контрольной суммы SHA-1 коммита, на который она указывает; поэтому операции с ветками являются дешёвыми с точки зрения потребления ресурсов или времени. Создание новой ветки в Git происходит так же быстро и просто как запись 41 байта в файл (40 знаков и перевод строки). __ ############ Одновременное создание новой ветки и переключение на неё ################# Как правило, при создании новой ветки вы хотите сразу на неё переключиться — это можно сделать используя команду: $ git checkout -b ####################### Основы ветвления и слияния ###################### Например, 1. Вы работаете над сайтом. 2. Вы создаете ветку для новой статьи, которую вы пишете. 3. Вы работаете в этой ветке. В этот момент вы получаете сообщение, что обнаружена критическая ошибка, требующая скорейшего исправления. Ваши действия: 4. Переключиться на основную ветку. 5. Создать ветку для добавления исправления. 6. После тестирования слить ветку содержащую исправление с основной веткой. 7. Переключиться назад в ту ветку, где вы пишете статью и продолжить работать. ########################### Основы ветвления ########################### Всё далее смотрим в графике: $ git log --oneline --decorate --graph --all [1.] Предположим, Вы работаете над проектом и уже имеете несколько коммитов. [2.] Вы решаете, что теперь вы будете заниматься проблемой #53 из вашей системы отслеживания ошибок. Чтобы создать ветку и сразу переключиться на нее, можно выполнить команду git checkout с параметром -b: $ git checkout -b iss53 Switched to a new branch "iss53" Это тоже самое что и: $ git branch iss53 AND $ git checkout iss53 __ Вы работаете над своим сайтом и делаете коммиты. Это приводит к тому, что ветка iss53 движется вперед, так как вы переключились на нее ранее (HEAD указывает на нее). [3.] $ vi index.html $ git commit -a -m 'added a new footer [issue 53]' __ Тут вы получаете сообщение об обнаружении уязвимости на вашем сайте, которую нужно немедленно устранить. Благодаря Git, не требуется размещать это исправление вместе с тем, что вы сделали в iss53. Комитим всё, что наделали и переключаемся на ветку master. [4.] $ git checkout master Switched to branch 'master' С этого момента ваш рабочий каталог имеет точно такой же вид, какой был перед началом работы над проблемой #53. Git возвращает состояние рабочего каталога к тому виду, какой он имел в момент последнего коммита в эту ветку. Он добавляет, удаляет и изменяет файлы автоматически, чтобы состояние рабочего каталога соответствовало тому, когда был сделан последний коммит. __ Пишим исправления... Давайте создадим новую ветку для исправления, в которой будем работать, пока не закончим исправление. [5.] $ git checkout -b hotfix Switched to a new branch 'hotfix' $ vi index.html // правим что то... $ git commit -a -m 'fixed the broken email address' [hotfix 1fb7853] fixed the broken email address 1 file changed, 2 insertions(+) __ Вы можете прогнать тесты, чтобы убедиться, что ваше исправление делает именно то, что нужно. И если это так — выполнить слияние ветки hotfix с веткой master для включения изменений в продукт. Это делается командой git merge: [6.] $ git checkout master $ git merge hotfix Updating f42c576..3a0874c Fast-forward index.html | 2 ++ 1 file changed, 2 insertions(+) Заметили фразу “fast-forward” в этом слиянии? Git просто переместил указатель ветки вперед, потому что коммит C4, на который указывает слитая ветка hotfix, был прямым потомком коммита C2, на котором вы находились до этого. Другими словами, если коммит сливается с тем, до которого можно добраться двигаясь по истории прямо, Git упрощает слияние просто перенося указатель ветки вперед, так как нет расхождений в изменениях. Это называется “fast-forward”. __ После внедрения вашего архиважного исправления вы готовы вернуться к работе над тем, что были вынуждены отложить. Но сначала нужно удалить ветку hotfix, потому что она больше не нужна — ветка master указывает на то же самое место. Для удаления ветки выполните команду git branch с параметром -d: $ git branch -d hotfix Deleted branch hotfix (3a0874c). Теперь вы можете переключиться обратно на ветку iss53 и продолжить работу над проблемой #53: [7.] $ git checkout iss53 Switched to branch "iss53" $ vi index.html $ git commit -a -m 'finished the new footer [issue 53]' [iss53 ad82d7a] finished the new footer [issue 53] 1 file changed, 1 insertion(+) Изменения из ветки hotfix не включены в вашу ветку iss53. Если их нужно включить, вы можете влить ветку master в вашу ветку iss53 командой git merge master, или же вы можете отложить слияние этих изменений до завершения работы, и затем влить ветку iss53 в master. ############################ Основы слияния ############################ Предположим, вы решили, что работа по проблеме #53 закончена и её можно влить в ветку master. Для этого нужно выполнить слияние ветки iss53 точно так же, как вы делали это с веткой hotfix ранее. Все что нужно сделать — переключиться на ветку, в которую вы хотите включить изменения, и выполнить команду git merge: $ git checkout master Switched to branch 'master' $ git merge iss53 Merge made by the 'recursive' strategy. index.html | 1 + 1 file changed, 1 insertion(+) Здесь Git выполняет простое трёхстороннее слияние используя последние коммиты объединяемых веток и общего для них родительского коммита. __ Изменения слиты, ветка iss53 больше не нужна. Вы можете закрыть задачу в системе отслеживания ошибок и удалить ветку: $ git branch -d iss53 Смотрим всё: $ git log --oneline --decorate --graph --all ######################################################################## ################## ##################### ################## MERGE + CONFLICTS ... ##################### ################## ##################### ######################################################################## ##################### Основные конфликты слияния ####################### Если вы изменили одну и ту же часть одного и того же файла по-разному в двух объединяемых ветках, Git не сможет их чисто объединить. Если ваше исправление ошибки #53 потребовало изменить ту же часть файла что и hotfix, вы получите примерно такое сообщение о конфликте слияния: $ git merge iss53 Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result. Git не создал коммит слияния автоматически. Он остановил процесс до тех пор, пока вы не разрешите конфликт. Чтобы в любой момент после появления конфликта увидеть, какие файлы не объединены, вы можете запустить git status: $ git status On branch master You have unmerged paths. (fix conflicts and run "git commit") Unmerged paths: (use "git add ..." to mark resolution) both modified: index.html no changes added to commit (use "git add" and/or "git commit -a") Всё, где есть неразрешённые конфликты слияния, перечисляется как неслитое. В конфликтующие файлы Git добавляет специальные маркеры конфликтов, чтобы вы могли исправить их вручную. В вашем файле появился раздел, выглядящий примерно так: $ vi index.html ... <<<<<<< HEAD:index.html ======= >>>>>>> iss53:index.html ... Это означает, что версия из HEAD (вашей ветки master, поскольку именно её вы извлекли перед запуском команды слияния) — это верхняя часть блока (всё, что над =======), а версия из вашей ветки iss53 представлена в нижней части. Чтобы разрешить конфликт, придётся выбрать один из вариантов, либо объединить содержимое по-своему. Например, вы можете разрешить конфликт, заменив весь блок следующим: В этом разрешении есть немного от каждой части, а строки <<<<<<<, ======= и >>>>>>> полностью удалены. Разрешив каждый конфликт во всех файлах, запустите git add для каждого файла, чтобы отметить конфликт как решённый. Добавление файла в индекс означает для Git, что все конфликты в нём исправлены. Если вы хотите использовать графический инструмент для разрешения конфликтов, можно запустить git mergetool, которое проведет вас по всем конфликтам: $ git mergetool This message is displayed because 'merge.tool' is not configured. See 'git mergetool --tool-help' or 'git help config' for more details. 'git mergetool' will now attempt to use one of the following tools: opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge Merging: index.html Normal merge conflict for 'index.html': {local}: modified file {remote}: modified file Hit return to start merge resolution tool (opendiff): Если вы хотите использовать инструмент слияния не по умолчанию (в данном случае Git выбрал opendiff, поскольку команда запускалась на Mac), список всех поддерживаемых инструментов представлен вверху после фразы “one of the following tools.” Просто введите название инструмента, который хотите использовать. __ Теперь можно снова запустить git status, чтобы убедиться в отсутствии конфликтов: $ git status On branch master All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: index.html Если это вас устраивает и вы убедились, что все файлы, где были конфликты, добавлены в индекс — выполните команду git commit для создания коммита слияния. Комментарий к коммиту слияния по умолчанию выглядит примерно так: Merge branch 'iss53' Conflicts: index.html # # It looks like you may be committing a merge. # If this is not correct, please remove the file # .git/MERGE_HEAD # and try again. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # All conflicts fixed but you are still merging. # # Changes to be committed: # modified: index.html # Если вы считаете, что коммит слияния требует дополнительных пояснений — опишите как были разрешены конфликты и почему были применены именно такие изменения, если это не очевидно. ################## Управление ветками ################## Без параметров, вы получите простой список имеющихся у вас веток: $ git branch iss53 * master testing Обратите внимание на символ *, стоящий перед веткой master: он указывает на ветку, на которой вы находитесь в настоящий момент (т.е. ветку, на которую указывает HEAD). __ Посмотреть последний коммит на каждой из веток, выполните команду git branch -v: $ git branch -v iss53 93b412c fix javascript issue * master 7a98805 Merge branch 'iss53' testing 782fd34 add scott to the author list in the readmes Опции --merged и --no-merged могут отфильтровать этот список для вывода только тех веток, которые слиты или ещё не слиты в текущую ветку. Чтобы посмотреть те ветки, которые вы уже слили с текущей, можете выполнить команду git branch --merged: $ git branch --merged iss53 * master Ветка iss53 присутствует в этом списке потому что вы ранее слили её в master. Те ветки из этого списка, перед которыми нет символа *, можно смело удалять командой git branch -d; наработки из этих веток уже включены в другую ветку, так что ничего не потеряется. __ Чтобы увидеть все ветки, содержащие наработки, которые вы пока ещё не слили в текущую ветку, выполните команду git branch --no-merged: $ git branch --no-merged testing Вы увидите оставшуюся ветку. Так как она содержит ещё не слитые наработки, попытка удалить её командой git branch -d приведёт к ошибке: $ git branch -d testing error: The branch 'testing' is not fully merged. If you are sure you want to delete it, run 'git branch -D testing'. Если вы действительно хотите удалить ветку вместе со всеми наработками, используйте опцию -D, как указано в подсказке. __ Если в качестве аргумента не указан коммит или ветка, то опции --merged и --no-merged покажут что уже слито или не слито с вашей текущей веткой соответственно. Вы всегда можете указать дополнительный аргумент для вывода той же информации, но относительно указанной ветки предварительно не извлекая и не переходя на неё. $ git checkout testing $ git branch --no-merged master topicA featureB ######################## Удалённые ветки ########################