Синхронизация с удаленными хранилищами#
Под синхронизацией подразумевается прием и передачу изменений из других хранилищ. Технически, это выглядит как приведение истории из разных хранилищ к одному виду.
В этом разделе мы:
познакомимся с командами
git remote,git push,git pull,git fetch;научимся отправлять и принимать изменения из удаленного хранилища;
будем различать локальные, удаленные и отслеживающие ветки;
научимся работать с одним и несколькими удаленными хранилищами.
Воспользовавшись вышеперечисленными командами мы смоделируем групповую работу над проектом в пределах одной файловой системы.
Работа с одним удаленным хранилищем#
Для работы с удаленным хранилищем нам необходимо знать как минимум о трех командах: git fetch, git push, git pull.
Команда git fetch забирает из удаленного хранилища изменения.
Но чтобы изменения там появились, их необходимо отправить туда.
Команда git push отправляет изменения из локального хранилища в удаленное.
Команда git pull забирает изменения из удаленного хранилища и сливает их с текущими.
Она представляет последовательность команд git fetch и git merge.
Зная эти команды, разберем сценарий one-remote-and-two-locals.sh, в котором два локальных хранилища взаимодействуют через удаленное.
Сценарий разбит на четыре эпизода, поочередно наполняющих файл main.c контентом в каждом из локальных хранилищ.
Сначала первое хранилище отправляет в удаленное пустой файл, а второе хранилище заполняет его содержимым
main()
{
return 0;
}
Затем первое хранилище добавляет в него тип возвращаемого значения, а второе – список аргументов функции main.
Первое хранилище успевает синхронизироваться с удаленным раньше, чем второе.
Поэтому второму приходится слиться с изменениями из удаленного, разрешив попутно конфликт слияния:
<<<<<<< HEAD
main(int argc, char** argv)
=======
int main()
>>>>>>> origin/main
{
return 0;
}
Локальная, удаленная и отслеживающая ветки#
В сценарии выше неопределенность представляет аргумент origin/main команды git merge.
Чтобы разобраться в ней нам следует понять как обозначают удаленные хранилища в локальном, что такое локальные, удаленные и отслежваемые ветки.
Склонированное локальное хранилище сохраняет связь со своим удаленным хранилищем.
Git удаленному хранилищу по умолчанию задает псевдоним origin.
Псевдоним заменяет более сложный в наборе url-адрес.
Другие команды, когда им потребуется обратиться к удаленному хранилищу, возьмут адрес связанный с именем origin.
Команда git remote перечисляет список сохраненных удаленных хранилищ, связанных с локальным.
origin будет показываться всегда.
Чтобы увидеть адреса хранилищ, выполните команду выше с опцией -v:
$ git remote -v
origin /home/bob/projects/git-examples/./remote.git (fetch)
origin /home/bob/projects/git-examples/./remote.git (push)
В подробном выводе с хранилищем связаны два адреса. Первый из них для чтения, а второй – для записи. Здесь они совпадают, но в общем случае отличаются.
После клонирования мы получаем идентичную локальную копию удаленного хранилища. В обоих хранилищах содержатся ветки, состояние которых в начальный момент совпадают. Но со временем ветки разойдутся: локальные будут наращиваться коммитами от автора локального хранилища, а удаленные – коммитами от других участников команды. В моменты слияния к веткам приходится обращаться, например, для слияния текущей ветки main с одноименной удаленной.
Как различить локальную и удаленную ветки, если их имена совпадают?
Удаленным веткам в локальном хранилище дают имена, составленные от имени удаленного хранилища: ветка main удаленного хранилища origin будет обозначена как origin/main.
В отличие от локальной ветки, указатель удаленной ветки перемещается только после синхронизации с удаленным хранилищем командами git fetch и git pull.
Положение удаленной ветки актуально на момент последней синхронизации.
Локальная ветка перемещается только при создании коммита и слияниях.
В удаленные ветки нельзя создавать коммиты.
Для этого сначала следует создать локальную ветку по удаленной.
Когда такая локальная ветка создается, в ней сохраняется связь с удаленной и ее называют отслеживающей.
При клонировании хранилища, автоматически создается локальная ветка main (master), отслеживающая удаленную ветку origin/main (origin/master).
Зная про эту связь, команда git pull самостоятельно определяет какую локальную ветку с какой удаленной слить.
Работа с несколькими удаленными хранилищами#
Разберем следующий сценарий, в котором два локальных хранилища взаимодействуют через удаленные хранилища каждого.
Хранилище remote-2.git – это удаленное хранилище, полученное клонированием другого удаленного хранилища remote-1.git.
Такой процесс в среде открытого ПО называют форком хранилища.
Локальное хранилище local-1 вносит в удаленное remote-1.git файл main.c со знакомым содержимым:
main()
{
return 0;
}
В процессе форка оно переносится во второе удаленное хранилище remote-2.git.
Затем параллельно через связку remote-1.git и local-1 в файл вносится тип возвращаемого значения, а связку remote-2.git и local-2 – аргументы функции main.
После этого локальное хранилище local-1 переносит изменения из remote-2.git в remote-1.git, попутно разрешая конфликт слияния.
На последнем этапе переноса изменений автор local-1 добавляет ссылку на второе удаленное хранилище командой git remote add remote-2 ../remote-2.git.
Команда добавляет ссылку на хранилище с псевдонимом remote-2 и адресом ../remote-2.git.
И уже этот псевдоним используется в командах git fetch и git merge.