Система версионного контроля GIT
Площадка для эксперементов
Логин: slavko.lht@gmail.com
Пароль: ********
Установка
Windows
Linux
yum install git-core
apt-get install git-core
Установка имени и электронной почты
git config --global user.name "Your Name"
git config --global user.email "your_email@whatever.com"
Параметры установки окончаний строк
для пользователей Unix/Mac
git config --global core.autocrlf input
git config --global core.safecrlf true
для пользователей Windows
git config --global core.autocrlf true
git config --global core.safecrlf true
Создайте страницу «Hello, World»
Начните работу с создания пустого каталога с именем «hello», затем войдите внего и создайте там файл с именем hello.html с таким содержанием.mkdir hello cd hello echo 'Hello, World' > hello.htmlФайл: hello.html
Hello, World
Создание репозитория
git init
$ git init Initialized empty Git repository in /users/slavko/hello/.git/
Добавьте страницу в репозиторий
Теперь давайте добавим в репозиторий страницу «Hello, World».
git add hello.html
git commit -m "First Commit"
$ git add hello.html $ git commit -m "First Commit" [master (root-commit) 911e8c9] First Commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 hello.html
Измените страницу «Hello, World»
Добавим кое-какие HTML-теги к нашему приветствию. Измените содержимое файла на:Файл: hello.html
<h1>Hello, World!</h1>
Проверьте состояние
Теперь проверьте состояние рабочего каталога
git status
$ git status # On branch master # Changes not staged for commit: # (use "git addПервое, что нужно заметить, это то, что git знает, что файл hello.html был изменен, но при этом эти изменения еще не зафиксированы в репозитории. Также обратите внимание на то, что сообщение о состоянии дает вам подсказку о том, что нужно делать дальше. Если вы хотите добавить эти изменения в репозиторий, используйте команду git add В противном случае используйте команду git сheckout для отмены изменений...." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: hello.html # no changes added to commit (use "git add" and/or "git commit -a")
Добавьте изменения - Индексация
Теперь дайте команду git проиндексировать изменения. Проверьте состояниеgit add hello.html
git status
$ git add hello.html $ git status # On branch master # Changes to be committed: # (use "git reset HEADИзменения файла hello.html были проиндексированы. Это означает, что git теперь знает об изменении, но изменение пока не перманентно (читай, навсегда) записано в репозиторий. Следующий коммит будет включать в себя проиндексированные изменения. Если вы решили, что не хотите коммитить изменения, команда состояния напомнит вам о том, что с помощью команды git reset можно снять индексацию этих изменений...." to unstage) # # modified: hello.html #
Фиксация изменений - Коммит
Давайте сделаем коммит того, что мы проиндексировали, в репозиторий. Когда вы ранее использовали git commit для коммита первоначальной версии файла hello.html в репозиторий, вы включили метку -m, которая делает комментарий в командной строке. Команда commit позволит вам интерактивно редактировать комментарии для коммита. Теперь давайте это проверим. Если вы опустите метку -m из командной строки, git перенесет вас в редактор по вашему выбору. Редактор выбирается из следующего списка (в порядке приоритета):git commit
git commit Waiting for Emacs... [master 569aa96] Added h1 tag 1 files changed, 1 insertions(+), 1 deletions(-)
git status
$ git status # On branch master nothing to commit (working directory clean)
Изменения, а не файлы
Большинство систем версионного контроля работают с файлами. Вы добавляете файл в версионный контроль, а система отслеживает изменения файла с этого момента. Git фокусируется на изменениях в файле, а не самом файле. Когда вы осуществляете команду git add file, вы не говорите git добавить файл в репозиторий. Скорее вы говорите, что git надо отметить текущее состояние файла, коммит которого будет произведен позже.История
получение списка произведенных изменений — функция команды git loggit log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=format:"%c" --shortstat
$ git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=format:"%c" * fa3c141 2011-03-09 | Added HTML header (HEAD, master) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]Давайте рассмотрим его в деталях:
Алиасы
алиасы и шорткаты для команд gitgit config --global alias.co checkout git config --global alias.ci commit git config --global alias.st status git config --global alias.br branch git config --global alias.hist 'log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=format:"%c"'Добавьте следующее в файл .gitconfig в вашем пользовательском $HOME каталоге
[alias] co = checkout ci = commit st = status br = branch hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=format:"%c"
Получение старых версий
Возвращаться назад в историю очень просто. Команда checkout скопирует любой снимок из репозитория в рабочий каталог.git checkout <hash>
$ git checkout 911e8c9 Note: checking out '911e8c9'. 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 new_branch_name HEAD is now at 911e8c9... First Commit $ cat hello.html Hello, WorldВернитесь к последней версии в ветке master
git checkout master
$ git checkout master Previous HEAD position was 911e8c9... First Commit Switched to branch 'master' $ cat hello.html <html> <head> </head> <body> <h1>Hello, World!</h1> </body> </html>
Создание тегов версий
Давайте назовем текущую версию страницы hello первой (v1)git tag v1 Давайте создадим тег для версии, которая идет перед текущей версией и назовем его v1-beta. В первую очередь нам надо переключиться на предыдущую версию. Вместо поиска до хэш, мы будем использовать ^, обозначающее «родитель v1». Если обозначение v1^ вызывает у вас какие-то проблемы, попробуйте также v1~1, указывающее на ту же версию. Это обозначение можно определить как «первую версию предшествующую v1».
git checkout v1^
git tag v1-beta
Переключение по имени тега
git checkout v1
git checkout v1-beta
Просмотр тегов с помощью команды tag
$ git tag v1 v1-betaПросмотр Тегов в логах
git hist master --all
$ git hist master --all * fa3c141 2011-03-09 | Added HTML header (v1, master) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (HEAD, v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]
Отмена локальных изменений (до индексации)
Переключитесь на ветку mastergit checkout master
Убедитесь, что вы находитесь на последнем коммите ветки master, прежде чем продолжить работу.
Измените hello.html
<html> <head> </head> <body> <h1>Hello, World!</h1> <!-- This is a bad comment. We want to revert it. --> </body> </html>Проверьте состояние git status
$ git status # On branch master # Changes not staged for commit: # (use "git addМы видим, что файл hello.html был изменен, но еще не проиндексирован...." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: hello.html # no changes added to commit (use "git add" and/or "git commit -a")
Отмена изменений в рабочем каталоге
Используйте команду checkout для переключения в версию файла hello.html в репозитории.
git checkout hello.html
$ git checkout hello.html $ git status # On branch master nothing to commit (working directory clean) $ cat hello.html <html> <head> </head> <body> <h1>Hello, World!</h1> </body> </html>Команда status показывает нам, что не было произведено никаких изменений, не зафиксированных в рабочем каталоге. И «нежелательный комментарий» больше не является частью содержимого файла.
Отмена проиндексированных изменений (перед коммитом)
git reset HEAD hello.html
Команда reset сбрасывает буферную зону к HEAD. Это очищает буферную зону от изменений, которые мы только что проиндексировали. Команда reset (по умолчанию) не изменяет рабочий каталог. Поэтому рабочий каталог все еще содержит нежелательный комментарий. Мы можем использовать команду checkout из предыдущего урока, чтобы удалить нежелательные изменения в рабочем каталоге.
Отмена коммитов
Иногда вы понимаете, что новые коммиты являются неверными, и хотите их отменить. Есть несколько способов решения этого вопроса, здесь мы будем использовать самый безопасный. Мы отменим коммит путем создания нового коммита, отменяющего нежелательные изменения.Измените файл и сделайте коммит
git add hello.html
git commit -m "Oops, we didn't want this commit"
Сделайте коммит с новыми изменениями, отменяющими предыдущие Чтобы отменить коммит, нам необходимо сделать коммит, который удаляет изменения, сохраненные нежелательным коммитом.
git revert HEAD --no-edit
Удаление коммиттов из ветки
Revert из предыдущего раздела является мощной командой, которая позволяет отменить любые коммиты в репозиторий. Однако, и оригинальный и «отмененный» коммиты видны в истории ветки (при использовании команды git log). Часто мы делаем коммит, и сразу понимаем, что это была ошибка. Было бы неплохо иметь команду «возврата», которая позволила бы нам сделать вид, что неправильного коммита никогда и не было. Команда «возврата» даже предотвратила бы появление нежелательного коммита в истории git logПри получении ссылки на коммит (т.е. хэш, ветка или имя тега), Команда reset
$ git reset --hard v1 HEAD is now at fa3c141 Added HTML header $ git hist * fa3c141 2011-03-09 | Added HTML header (HEAD, v1, master) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]Ничего никогда не теряется
git hist --all
$ git hist --all * 45fa96b 2011-03-09 | Revert "Oops, we didn't want this commit" (oops) [Marina Pushkova] * 846b90c 2011-03-09 | Oops, we didn't want this commit [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (HEAD, v1, master) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]
Удаление тега oops (уборка)
Тег oops свою функцию выполнил. Давайте удалим его и коммиты, на которые он ссылался, сборщиком мусора.git tag -d oops
git status
$ git tag -d oops Deleted tag 'oops' (was 45fa96b) $ git hist --all * fa3c141 2011-03-09 | Added HTML header (HEAD, v1, master) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]
Внесение изменений в коммиты
Измените страницу, а затем сделайте коммит После совершения коммита вы понимаете, что любой хороший комментарий должен включать электронную почту автора. Обновите страницу hello.html, включив в нее email.git add hello.html
git commit --amend -m "Add an author/email comment"
$ git hist * 6a78635 2011-03-09 | Add an author/email comment (HEAD, master) [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (v1) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]
Перемещение файлов
Переместите файл hello.html в каталог libgit mv hello.html lib
$ mkdir lib $ git mv hello.html lib $ git status # On branch master # Changes to be committed: # (use "git reset HEADПеремещая файлы с помощью git, мы информируем git о 2 вещах..." to unstage) # # renamed: hello.html -> lib/hello.html #
Config File
cat .git/config
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true [user] name = Marina Pushkova email = marina (at) githowto.comЭто файл конфигурации, создающийся для каждого конкретного проекта. Записи в этом файле будут перезаписывать записи в файле .gitconfig вашего главного каталога, по крайней мере в рамках этого проекта.
Файл HEAD
cat .git/HEAD
$ cat .git/HEAD ref: refs/heads/masterФайл HEAD содержит ссылку на текущую ветку, в данный момент это должна быть ветка master.
Создание ветки
git checkout -b style
git add lib/style.css git commit -m "Added css stylesheet" git add lib/hello.html git commit -m "Hello uses style.css" git add index.html git commit -m "Updated index.html"Теперь у нас есть новая ветка под названием style с 3 новыми коммитами.
Навигация по веткам
git hist --all
$ git hist --all * 07a2a46 2011-03-09 | Updated index.html (HEAD, style) [Marina Pushkova] * 649d26c 2011-03-09 | Hello uses style.css [Marina Pushkova] * 1f3cbd2 2011-03-09 | Added css stylesheet [Marina Pushkova] * 8029c07 2011-03-09 | Added index.html. (master) [Marina Pushkova] * 567948a 2011-03-09 | Moved hello.html to lib [Marina Pushkova] * 6a78635 2011-03-09 | Add an author/email comment [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (v1) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]
Переключение на ветку master git checkout master
Переключение на ветку style git checkout style
Слияние веток
Слияние переносит изменения из двух веток в одну. Давайте вернемся к ветке style и сольем master с style.git checkout style
git merge master
git hist --all
$ git checkout style Switched to branch 'style' $ git merge master Merge made by recursive. README | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 README $ git hist --all * 5813a3f 2011-03-09 | Merge branch 'master' into style (HEAD, style) [Marina Pushkova] |\ | * 6c0f848 2011-03-09 | Added README (master) [Marina Pushkova] * | 07a2a46 2011-03-09 | Updated index.html [Marina Pushkova] * | 649d26c 2011-03-09 | Hello uses style.css [Marina Pushkova] * | 1f3cbd2 2011-03-09 | Added css stylesheet [Marina Pushkova] |/ * 8029c07 2011-03-09 | Added index.html. [Marina Pushkova] * 567948a 2011-03-09 | Moved hello.html to lib [Marina Pushkova] * 6a78635 2011-03-09 | Add an author/email comment [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (v1) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]Путем периодического слияния ветки master с веткой style вы можете переносить из master любые изменения и поддерживать совместимость изменений style с изменениями в основной ветке. Однако, это делает графики коммитов действительно уродливыми. Позже мы рассмотрим возможность перебазирования, как альтернативы слиянию.
Разрешение конфликтов
$ git checkout style Switched to branch 'style' $ git merge master Auto-merging lib/hello.html CONFLICT (content): Merge conflict in lib/hello.html Automatic merge failed; fix conflicts and then commit the result.Если вы откроете lib/hello.html вы увидите
<html> <head> <<<<<<< HEAD <link type="text/css" rel="stylesheet" media="all" href="style.css" /> ======= <!-- no style --> >>>>>>> master </head> <body> <h1>Hello,World! Life is great!</h1> </body> </html>Вам необходимо вручную разрешить конфликт. Внесите изменения в lib/hello.html для достижения следующего результата.
$ git add lib/hello.html $ git commit -m "Merged master fixed conflict." Recorded resolution for 'lib/hello.html'. [style 645c4e6] Merged master fixed conflict.
Перебазирование
перенести изменения в master в нашу ветку stylegit checkout style
git rebase master
$ git checkout style Switched to branch 'style' $ $ git rebase master First, rewinding head to replay your work on top of it... Applying: Added css stylesheet Applying: Hello uses style.css Applying: Updated index.html $ $ git hist * 6e6c76a 2011-03-09 | Updated index.html (HEAD, style) [Marina Pushkova] * 1436f13 2011-03-09 | Hello uses style.css [Marina Pushkova] * 59da9a7 2011-03-09 | Added css stylesheet [Marina Pushkova] * 6c0f848 2011-03-09 | Added README (master) [Marina Pushkova] * 8029c07 2011-03-09 | Added index.html. [Marina Pushkova] * 567948a 2011-03-09 | Moved hello.html to lib [Marina Pushkova] * 6a78635 2011-03-09 | Add an author/email comment [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (v1) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]Конечный результат перебазирования очень похож на результат слияния. Ветка style в настоящее время содержит все свои изменения, а также все изменения ветки master. Однако, дерево коммитов значительно отличается. Дерево коммитов ветки style было переписано таким образом, что ветка master является частью истории коммитов. Это делает цепь коммитов линейной и гораздо более читабельной.
Когда использовать перебазирование, а когда слияние?
Не используйте перебазирование:Клонирование репозиториев
Создайте клон репозитория hellogit clone hello cloned_hello
$ git clone hello cloned_hello Cloning into cloned_hello... done. $ ls cloned_hello hello
Просмотр клонированного репозитория
cd cloned_hello
$ git hist --all * 6e6c76a 2011-03-09 | Updated index.html (HEAD, origin/master, origin/style, origin/HEAD, master) [Marina Pushkova] * 1436f13 2011-03-09 | Hello uses style.css [Marina Pushkova] * 59da9a7 2011-03-09 | Added css stylesheet [Marina Pushkova] * 6c0f848 2011-03-09 | Added README [Marina Pushkova] * 8029c07 2011-03-09 | Added index.html. [Marina Pushkova] * 567948a 2011-03-09 | Moved hello.html to lib [Marina Pushkova] * 6a78635 2011-03-09 | Add an author/email comment [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (v1) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]Вы увидите ветку master (HEAD) в списке истории. Вы также увидите ветки со странными именами (origin/master, origin/style и origin/HEAD)
Что такое origin?
имена удаленных репозиториевgit remote
$ git remote originМы видим, что клонированный репозиторий знает об имени по умолчанию удаленного репозитория
git remote show origin
$ git remote show origin * remote origin Fetch URL: /users/slavko/hello Push URL: /users/slavko/hello HEAD branch (remote HEAD is ambiguous, may be one of the following): style master Remote branches: style tracked master 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)
Список удаленных веток
Для того, чтобы увидеть все ветки, попробуйте следующую команду:git branch -a
$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/style remotes/origin/masterGit выводит все коммиты в оригинальный репозиторий, но ветки в удаленном репозитории не рассматриваются как локальные. Если мы хотим собственную ветку style, мы должны сами ее создать.
Извлечение изменений из удаленного репозитория
git fetch
git hist --all
$ git fetch From /users/slavko/hello 6e6c76a..2faa4ea master -> origin/master $ git hist --all * 2faa4ea 2011-03-09 | Changed README in original repo (origin/master, origin/HEAD) [Marina Pushkova] * 6e6c76a 2011-03-09 | Updated index.html (HEAD, origin/style, master) [Marina Pushkova] * 1436f13 2011-03-09 | Hello uses style.css [Marina Pushkova] * 59da9a7 2011-03-09 | Added css stylesheet [Marina Pushkova] * 6c0f848 2011-03-09 | Added README [Marina Pushkova] * 8029c07 2011-03-09 | Added index.html. [Marina Pushkova] * 567948a 2011-03-09 | Moved hello.html to lib [Marina Pushkova] * 6a78635 2011-03-09 | Add an author/email comment [Marina Pushkova] * fa3c141 2011-03-09 | Added HTML header (v1) [Marina Pushkova] * 8c32287 2011-03-09 | Added standard HTML page tags (v1-beta) [Marina Pushkova] * 43628f7 2011-03-09 | Added h1 tag [Marina Pushkova] * 911e8c9 2011-03-09 | First Commit [Marina Pushkova]На данный момент в репозитории есть все коммиты из оригинального репозитория, но они не интегрированы в локальные ветки клонированного репозитория.
В истории выше найдите коммит «Changed README in original repo». Обратите внимание, что коммит включает в себя коммиты «origin/master» и «origin/HEAD».
Теперь давайте посмотрим на коммит «Updated index.html». Вы увидите, что локальная ветка master указывает на этот коммит, а не на новый коммит, который мы только что извлекли.
Выводом является то, что команда «git fetch» будет извлекать новые коммиты из удаленного репозитория, но не будет сливать их с вашими наработками в локальных ветках.
Слияние извлеченных изменений
Слейте извлеченные изменения в локальную ветку mastergit merge origin/master
$ git merge origin/master Updating 6e6c76a..2faa4ea Fast-forward README | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)git pull = git fetch & git merge origin/master
Добавление ветки наблюдения
Ветки, которые начинаются с remotes/origin являются ветками оригинального репозитория. Обратите внимание, что у вас больше нет ветки под названием style, но он знает, что в оригинальном репозитории ветка style была.git branch --track style origin/style
git branch -a
git hist --max-count=2
$ git branch --track style origin/style Branch style set up to track remote branch style from origin. $ git branch -a style * master remotes/origin/HEAD -> origin/master remotes/origin/style remotes/origin/master $ git hist --max-count=2 * 2faa4ea 2011-03-09 | Changed README in original repo (HEAD, origin/master, origin/HEAD, master) [Marina Pushkova] * 6e6c76a 2011-03-09 | Updated index.html (origin/style, style) [Marina Pushkova]Теперь мы можем видеть ветку style в списке веток и логе.
Чистые репозитории
Чистые репозитории (без рабочих каталогов) обычно используются для расшаривания.Небольшое пояснение, что же все-таки означает «чистый репозиторий». Обычный git-репозиторий подразумевает, что вы будете использовать его как рабочую директорию, поэтому вместе с файлами проекта в актуальной версии, git хранит все служебные, «чисто-репозиториевские» файлы в поддиректории .git В удаленных репозиториях нет смысла хранить рабочие файлы на диске (как это делается в рабочих копиях), а все что им действительно нужно — это дельты изменений и другие бинарные данные репозитория. Вот это и есть «чистый репозиторий»
git clone --bare hello hello.git
$ git clone --bare hello hello.git Cloning into bare repository hello.git... done. $ ls hello.git HEAD config description hooks info objects packed-refs refsКак правило, репозитории, оканчивающиеся на «.git» являются чистыми репозиториями. Мы видим, что в репозитории hello.git нет рабочего каталога. По сути, это есть не что иное, как каталог .git нечистого репозитория.
Добавление удаленного репозитория
Давайте добавим репозиторий hello.git к нашему оригинальному репозиториюcd hello
git remote add shared ../hello.git
Отправка изменений в удаленный репозиторий
git push shared master
$ git push shared master To ../hello.git 2faa4ea..79f507c master -> master
Извлечение общих изменений
cd ../cloned_hello git remote add shared ../hello.git git branch --track shared master git pull shared master
Обьединение двух (и более) репозиториев
пусть будут 4 каталога с репозиториями git1,git2,git3,unite
в каждом из каталогов должна быть ветка master
т.е. выполнены 2 команды git add . & git commit -m 'init'
$ mkdir git1 $ cd git1 $ git init $ echo 'git1' > git1.txt $ git add . $ git commit -m 'git1 init' $ cd .. $ mkdir git2 $ cd git2 $ git init $ echo 'git2' > git2.txt $ git add . $ git commit -m 'git2 init' $ cd .. $ mkdir git3 $ cd git3 $ git init $ echo 'git3' > git3.txt $ git add . $ git commit -m 'git3 init' $ cd .. $ mkdir unite $ cd unite $ git init $ echo 'unite' > unite.txt $ git add . $ git commit -m 'unite init'
созданы 4 директория с репозиториями, пока они однозначны, но один директорий носит предательское имя unite что выдает его за сборщик других трех репозиториев git1,git2,git3 переходим в директорию unite и выполняем команды
$ cd unite $ git remote add -f git1 ../git1 $ git remote add -f git2 ../git2 $ git remote add -f git3 ../git3
чтобы посмотреть список всех подключенных удаленных репозиториев
$ git remote git1 git2 git3
теперь сливаем удаленные ветки в ветку master репозитория unite, опция --no-edit - комментарий коммита по умолчанию (без редактора)
$ git merge git1/master --no-edit $ git merge git2/master --no-edit $ git merge git3/master --no-edit
в каталоге unite видим файлы из всех удаленных репозиториев
$ ls git1.txt git2.txt git3.txt unite.txt
смотрим коммиты git log
$ git hist * bc9f7c7 02.03.2019 17:35:09 | Merge remote-tracking branch 'git3/master' (HEAD -> master) [SlavKoVrn] |\ | * 40add1b 02.03.2019 17:23:58 | git3 init (git3/master) [SlavKoVrn] * 55fe75f 02.03.2019 17:35:01 | Merge remote-tracking branch 'git2/master' [SlavKoVrn] |\ | * cc01f45 02.03.2019 17:23:11 | git2 init (git2/master) [SlavKoVrn] * d0d1b39 02.03.2019 17:34:51 | Merge remote-tracking branch 'git1/master' [SlavKoVrn] |\ | * 2a4fe20 02.03.2019 17:22:32 | git1 init (git1/master) [SlavKoVrn] * 7353059 02.03.2019 17:24:49 | unite init [SlavKoVrn]
теперь изменим чтонить скажем в репо git1 и зафиксируем это коммитом
$ cd ../git1 $ echo ' - changes' >> git1.txt $ git add . $ git commit -m 'changes in git1'
переходим в обьедененный репо unite и закачиваем изменения со всех репо
команда git fetch --all
$ cd ../unite $ git fetch --all Fetching git1 remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From ../git1 2a4fe20..9df2a2f master -> git1/master Fetching git2 Fetching git3
видно что изменения закачены только с каталога git1, поэтому и сливаем только ветку git1/master
$ git merge git1/master --no-edit Merge made by the 'recursive' strategy. git1.txt | 1 + 1 file changed, 1 insertion(+)
смотрим историю git log
$ git hist * 257138a 02.03.2019 17:57:01 | Merge remote-tracking branch 'git1/master' (HEAD -> master) [SlavKoVrn] |\ | * 9df2a2f 02.03.2019 17:48:14 | changes in git1 (git1/master) [SlavKoVrn] * | bc9f7c7 02.03.2019 17:35:09 | Merge remote-tracking branch 'git3/master' [SlavKoVrn] |\ \ | * | 40add1b 02.03.2019 17:23:58 | git3 init (git3/master) [SlavKoVrn] | / * | 55fe75f 02.03.2019 17:35:01 | Merge remote-tracking branch 'git2/master' [SlavKoVrn] |\ \ | * | cc01f45 02.03.2019 17:23:11 | git2 init (git2/master) [SlavKoVrn] | / * | d0d1b39 02.03.2019 17:34:51 | Merge remote-tracking branch 'git1/master' [SlavKoVrn] |\ \ | |/ | * 2a4fe20 02.03.2019 17:22:32 | git1 init [SlavKoVrn] * 7353059 02.03.2019 17:24:49 | unite init [SlavKoVrn]
видим наш коммит changes in git1
открываем файл git1.txt и видим наши изменения из репозитория git1
git1 - changes