[содержание](/readme.md) TODO: написать про ветвления и слияния # Системы контроля версий **Цель работы**: ознакомиться с основами системы контроля версий Git ## Теоретические сведения ### О контроле версий **Система контроля версий** (СКВ) — это система, регистрирующая изменения в одном или нескольких файлах с тем, чтобы в дальнейшем была возможность вернуться к определённым старым версиям этих файлов. Программисты обычно помещают в систему контроля версий исходные коды программ, но на самом деле под версионный контроль можно поместить файлы практически любого типа. Если вы графический или веб­дизайнер и хотели бы хранить каждую версию изображения или макета, то пользоваться системой контроля версий будет очень мудрым решением. СКВ даёт возможность возвращать отдельные файлы к прежнему виду, возвращать к прежнему состоянию весь проект, просматривать происходящие со временем изменения, определять, кто последним вносил изменения во внезапно переставший работать модуль, кто и когда внёс в код какую­-то ошибку, и многое другое. Вообще, если, пользуясь СКВ, вы всё испортите или потеряете файлы, всё можно будет легко восстановить. Вдобавок, накладные расходы будут очень маленькими. ### Распределённые системы контроля версий Про *локальные* и *централизованные* СКВ мы говорили на лекциях, здесь мы рассмотрим только *распределённые* системы контроля версий (РСКВ). В таких системах как *Git*, *Mercurial*, *Bazaar* или *Darcs* клиенты не просто выгружают последние версии файлов, а полностью копируют весь репозиторий (репозиторий ­ место, где хранятся и поддерживаются какие­-либо данные, в данном случае, данные, находящиеся под версионным контролем). Поэтому в случае, когда "умирает" сервер, через который шла работа, любой клиентский репозиторий может быть скопирован обратно на сервер, чтобы восстановить базу данных. Каждый раз, когда клиент забирает свежую версию файлов, он создаёт себе полную копию всех данных. ![](/img/skv_01.png) Кроме того, в большей части этих систем можно работать с несколькими удалёнными репозиториями, таким образом, можно одновременно работать по-­разному с разными группами людей в рамках одного проекта. Так, в одном проекте можно одновременно вести несколько типов рабочих процессов, что невозможно в централизованных системах. ### Основы Git #### Почти все операции — локальные Для совершения большинства операций в Git'е необходимы только локальные файлы и ресурсы, т.е. обычно информация с других компьютеров в сети не нужна. Поскольку вся история проекта хранится локально у вас на диске, большинство операций кажутся практически мгновенными. К примеру, чтобы показать историю проекта, Git'у не нужно скачивать её с сервера, он просто читает её прямо из вашего локального репозитория. Поэтому историю вы увидите практически мгновенно. Если вам нужно просмотреть изменения между текущей версией файла и версией, сделанной месяц назад, Git может взять файл месячной давности и вычислить разницу на месте, вместо того чтобы запрашивать разницу у СКВ-­сервера или качать с него старую версию файла и делать локальное сравнение. Кроме того, работа локально означает, что мало чего нельзя сделать без доступа к Сети или VPN. Если вы в самолёте или в поезде и хотите немного поработать, можно спокойно делать коммиты, а затем отправить их, как только станет доступна сеть. Если вы пришли домой, а VPN-­клиент не работает, всё равно можно продолжать работать. Во многих других системах это невозможно или же крайне неудобно. Например, используя Perforce, вы мало что можете сделать без соединения с сервером. Работая с Subversion и CVS, вы можете редактировать файлы, но сохранить изменения в вашу базу данных нельзя (потому что она отключена от репозитория). #### Git следит за целостностью данных Перед сохранением любого файла Git вычисляет контрольную сумму, и она становится индексом этого файла. Поэтому невозможно изменить содержимое файла или каталога так, чтобы Git не узнал об этом. Эта функциональность встроена в сам фундамент Git'а и является важной составляющей его философии. Если информация потеряется при передаче или повредится на диске, Git всегда это выявит. Механизм, используемый Git'ом для вычисления контрольных сумм, называется SHA­1 хешем. Это строка из 40 шестнадцатеричных символов (0­9 и a­f), вычисляемая в Git'е на основе содержимого файла или структуры каталога. SHA­1 хеш выглядит примерно так: ``` 24b9da6552252987aa493b52f8696cd6d3b00373 ``` Работая с Git'ом, вы будете встречать эти хеши повсюду, поскольку он их очень широко использует. Фактически, в своей базе данных Git сохраняет всё не по именам файлов, а по хешам их содержимого. #### Чаще всего данные в Git только добавляются Практически все действия, которые вы совершаете в Git'е, только добавляют данные в базу. Очень сложно заставить систему удалить данные или сделать что­то неотменяемое. Можно, как и в любой другой СКВ, потерять данные, которые вы ещё не сохранили, но как только они зафиксированы, их очень сложно потерять, особенно если вы регулярно отправляете изменения в другой репозиторий. #### Три состояния Это самое важное, что нужно помнить про Git, если вы хотите, чтобы изучение шло гладко. В Git'е файлы могут находиться в одном из трёх состояний: *зафиксированном*, *изменённом* и *подготовленном*. * К **изменённым** относятся файлы, которые поменялись, но ещё не были зафиксированы. * **Подготовленные** файлы — это изменённые файлы, отмеченные для включения в следующий коммит (git add). * **Зафиксированный** означает, что файл уже сохранён в вашей локальной базе (git commit). Таким образом, в проектах, использующих Git, есть три части: каталог Git'а (Git directory), рабочий каталог (working directory) и область подготовленных файлов (staging area). ![](/img/skv_02.png) **Каталог Git'а** — это место, где Git хранит метаданные и базу данных объектов вашего проекта. Это наиболее важная часть Git'а, и именно она копируется, когда вы клонируете репозиторий с другого компьютера. **Рабочий каталог** — это извлечённая из базы копия определённой версии проекта. Эти файлы достаются из сжатой базы данных в каталоге Git'а и помещаются на диск для того, чтобы вы их просматривали и редактировали. **Область подготовленных файлов** — это обычный файл, обычно хранящийся в каталоге Git'а, который содержит информацию о том, что должно войти в следующий коммит. Иногда его называют индексом (index), но в последнее время становится стандартом называть его областью подготовленных файлов (staging area). Стандартный рабочий процесс с использованием Git'а выглядит примерно так: 1. Вы вносите изменения в файлы в своём рабочем каталоге. 2. Подготавливаете файлы, добавляя их слепки в область подготовленных файлов. 3. Делаете коммит, который берёт подготовленные файлы из индекса и помещает их в каталог Git'а на постоянное хранение. Если рабочая версия файла совпадает с версией в каталоге Git'а, файл считается зафиксированным. Если файл изменён, но добавлен в область подготовленных данных, он подготовлен. Если же файл изменился после выгрузки из БД, но не был подготовлен, то он считается изменённым. ## Практическая часть С системой контроля версий можно работать многими способами: далее будет рассмотрена работа с Git через консоль. ### Установите Git если ее еще нет на вашем компьютере. >Используйте командную оболочку Git Bash, входящую в состав Git, потому что так вы сможете запускать сложные команды, приведённые в примерах. Командная оболочка Windows использует иной синтаксис, из­-за чего примеры в ней могут работать некорректно. ### Первоначальная настройка Git Теперь, когда Git установлен в вашей системе, необходимо настроить среду для работы с Git'ом под себя. Это нужно сделать только один раз — при обновлении версии Git'а настройки сохранятся. Но вы можете поменять их в любой момент, выполнив те же команды снова. В Git'е есть команда ``git config``, которая позволяет просматривать и устанавливать параметры, контролирующие все аспекты работы Git'а и его внешний вид. #### Имя пользователя Первое, что вам следует сделать после установки Git'а, — указать ваше имя и адрес электронной почты. Это важно, потому что каждый коммит в Git'е содержит эту информацию, и она включена в коммиты, передаваемые вами, и не может быть далее изменена: ``` git config ­­--global user.name "John Doe" git config ­­--global user.email johndoe@example.com ``` **Внимание!!!** Глобальные настройки (параметр *global*) нужно делать только на личном компьютере. В колледже этого делать не нужно. Настройки имени и почты нужно делать без параметра *global* в своем репозитории. #### Проверка настроек Если вы хотите проверить используемые настройки, можете использовать команду ``git config --­­list``: ``` git config ­­--list user.name=Scott Chacon user.email=schacon@gmail.com ... ``` ### Создание Git-репозитория Для создания Git-­репозитория существуют два основных подхода. **Первый** подход — импорт в Git уже существующего проекта или каталога. **Второй** — клонирование уже существующего репозитория с сервера. #### Создание репозитория в существующем проекте Для начала нужно создать **пустой** git-репозиторий (не ставить галочку у "создать readme") ![](/img/skv_04.png) При создании пустого репозитория сервер показывает какие команды нужно выполнить для инициализации локального репозитория и отправки его в удаленный репозиторий: ``` git init git add README.md git commit -m "first commit" git remote add origin https://github.com/kolei/empty.git git push -u origin master ``` Рассмотрим эти команды подробнее: * **git init** - эта команда создаёт в текущем каталоге новый подкаталог с именем *.git* содержащий все необходимые файлы репозитория. На этом этапе ваш проект ещё не находится под версионным контролем. * **git add README.md** - добавляет под версионный контроль файл *README.md* (напоминаю, это только пример, вам здесь нужно добавить свои файлы). Чтобы проиндексировать все файлы, можно вместо имени файла указать точку или звездочку **git add .** * **git commit -m "first commit"** - сохраняет текущее состояние в локальном репозитории. * **git remote add origin https://github.com/kolei/empty.git** - добавляет в настройки репозитория адрес удаленного git-репозитория. Здесь **origin** - это алиас (короткое имя) для репозитория. * **git push -u origin master** - отправляет локальный репозиторий на удаленный сервер. #### Клонирование существующего репозитория Клонирование существующего репозитория осуществляется командой ``git clone [url]``. Например, если вы хотите клонировать эти лекции, вы можете сделать это следующим образом: ``` git clone https://github.com/kolei/oap ``` Эта команда создаёт каталог с именем **oap**, инициализирует в нём каталог .git, скачивает все данные для этого репозитория и создаёт (checks out) рабочую копию последней версии. Если вы зайдёте в новый каталог oap, вы увидите в нём проектные файлы, пригодные для работы и использования. Если вы хотите клонировать репозиторий в каталог, отличный от oap, можно это указать в следующем параметре командной строки: ``` git clone https://github.com/kolei/oap myoap ``` Эта команда делает всё то же самое, что и предыдущая, только результирующий каталог будет назван myoap. ### Запись изменений в репозиторий Итак, у вас имеется Git-­репозиторий и рабочая копия файлов для некоторого проекта. Вам нужно делать некоторые изменения и фиксировать “снимки” состояния (snapshots) этих изменений в вашем репозитории каждый раз, когда проект достигает состояния, которое вам хотелось бы сохранить. ![](/img/skv_03.png) Запомните, каждый файл в вашем рабочем каталоге может находиться в одном из двух состояний: под версионным контролем (отслеживаемые) и нет (неотслеживаемые). Отслеживаемые файлы — это те файлы, которые были в последнем слепке состояния проекта (snapshot); они могут быть неизменёнными, изменёнными или подготовленными к коммиту (staged). Неотслеживаемые файлы — это всё остальное, любые файлы в вашем рабочем каталоге, которые не входили в ваш последний слепок состояния и не подготовлены к коммиту. Когда вы впервые клонируете репозиторий, все файлы будут отслеживаемыми и неизменёнными, потому что вы только взяли их из хранилища (checked them out) и ничего пока не редактировали. Как только вы отредактируете файлы, Git будет рассматривать их как изменённые, т.к. вы изменили их с момента последнего коммита. Вы индексируете (stage) эти изменения и затем фиксируете все индексированные изменения, а затем цикл повторяется. #### Определение состояния файлов Основной инструмент, используемый для определения, какие файлы в каком состоянии находятся — это команда ``git status``. Если вы выполните эту команду сразу после клонирования, вы увидите что­то вроде этого: ``` git status On branch master nothing to commit, working directory clean ``` Это означает, что у вас чистый рабочий каталог, другими словами — в нём нет отслеживаемых изменённых файлов. Git также не обнаружил неотслеживаемых файлов, в противном случае они бы были перечислены здесь. И наконец, команда сообщает вам на какой ветке (branch) вы сейчас находитесь. Пока что это всегда ветка master — это ветка по умолчанию (про ветки мы поговорим ниже). #### Отслеживание новых файлов Для того чтобы начать отслеживать (добавить под версионный контроль) новый файл, используется команда ``git add``. Например, чтобы начать отслеживание файла README, вы можете выполнить следующее: ``` git add README ``` Если вы выполните команду status, то увидите, что файл README теперь отслеживаемый и индексированный: ``` git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: README ``` Вы можете видеть, что файл проиндексирован по тому, что он находится в секции “Changes to be committed”. Если вы выполните коммит в этот момент, то версия файла, существовавшая на момент выполнения вами команды ``git add``, будет добавлена в историю снимков состояния. Как вы помните, когда вы ранее выполнили ``git init``, вы затем выполнили git add (файлы) — это было сделано для того, чтобы добавить файлы в вашем каталоге под версионный контроль. Команда git add принимает параметром путь к файлу или каталогу, если это каталог, команда рекурсивно добавляет (индексирует) все файлы в данном каталоге. Для добавления всех файлов проекта можно выполнить команду ``` git add . ``` Она проиндексирует все новые и изменившиеся файлы #### Индексация изменённых файлов Давайте модифицируем файл, уже находящийся под версионным контролем. Если вы измените отслеживаемый файл benchmarks.rb и после этого снова выполните команду status, то результат будет примерно следующим: ``` git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: README Changes not staged for commit: (use "git add ..." to update what will be committed) modified: benchmarks.rb ``` Файл benchmarks.rb находится в секции “Changes not staged for commit” — это означает, что отслеживаемый файл был изменён в рабочем каталоге, но пока не проиндексирован. Чтобы проиндексировать его, необходимо выполнить команду ``git add`` (это многофункциональная команда, она используется для добавления под версионный контроль новых файлов, для индексации изменений, а также для других целей, например для указания файлов с исправленным конфликтом слияния). Выполним ``git add``, чтобы проиндексировать benchmarks.rb, а затем снова выполним ``git status``: ``` git add benchmarks.rb git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: README modified: benchmarks.rb ``` Теперь оба файла проиндексированы и войдут в следующий коммит. В этот момент вы, предположим, вспомнили одно небольшое изменение, которое вы хотите сделать в benchmarks.rb до фиксации. Вы открываете файл, вносите и сохраняете необходимые изменения и вроде бы готовы к коммиту. Но давайте ещё раз выполним ``git status``: ``` git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: README modified: benchmarks.rb Changes not staged for commit: (use "git add ..." to update what will be committed) modified: benchmarks.rb ``` Теперь benchmarks.rb отображается как проиндексированный и непроиндексированный одновременно. Как такое возможно? Такая ситуация наглядно демонстрирует, что Git индексирует файл в точности в том состоянии, в котором он находился, когда вы выполнили команду ``git add``. Если вы выполните коммит сейчас, то файл benchmarks.rb попадёт в коммит в том состоянии, в котором он находился, когда вы последний раз выполняли команду ``git add``, а не в том, в котором он находится в вашем рабочем каталоге в момент выполнения ``git commit``. Если вы изменили файл после выполнения ``git add``, вам придётся снова выполнить ``git add``, чтобы проиндексировать последнюю версию файла: ``` git add benchmarks.rb git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: README modified: benchmarks.rb ``` #### Игнорирование файлов Зачастую, у вас имеется группа файлов, которые вы не только не хотите автоматически добавлять в репозиторий, но и видеть в списках неотслеживаемых. К таким файлам обычно относятся автоматически генерируемые файлы (различные логи, результаты сборки программ и т.п.). В таком случае, вы можете создать в корне проекта файл *.gitignore* с перечислением шаблонов соответствующих таким файлам. Вот пример файла *.gitignore*: ``` *.[oa] *~ ``` Первая строка предписывает Git'у игнорировать любые файлы заканчивающиеся на .o или .a — объектные и архивные файлы, которые могут появиться во время сборки кода. Вторая строка предписывает игнорировать все файлы заканчивающиеся на тильду (~), которая используется во многих текстовых редакторах, например Emacs, для обозначения временных файлов. Вы можете также включить каталоги log, tmp или pid; автоматически создаваемую документацию; и т.д. и т.п. Хорошая практика заключается в настройке файла *.gitignore* до того, как начать серьёзно работать, это защитит вас от случайного добавления в репозиторий файлов, которых вы там видеть не хотите. #### Фиксация изменений Теперь, когда ваш индекс настроен так, как вам и хотелось, вы можете зафиксировать свои изменения. Запомните, всё, что до сих пор не проиндексировано — любые файлы, созданные или изменённые вами, и для которых вы не выполнили ``git add`` после момента редактирования — не войдут в этот коммит. Они останутся изменёнными файлами на вашем диске. В нашем случае, когда вы в последний раз выполняли ``git status``, вы видели что всё проиндексировано, и вот, вы готовы к коммиту. Простейший способ зафиксировать изменения — это набрать ``git commit``: ``` git commit ``` Эта команда откроет выбранный вами текстовый редактор. (Редактор устанавливается системной переменной $EDITOR — обычно это vim или emacs, хотя вы можете установить ваш любимый с помощью команды ``git config --­­global core.editor``). В редакторе будет отображён следующий текст (это пример окна Vim'а): ``` #Please enter the commit message for your changes. Lines starting #with '#' will be ignored, and an empty message aborts the commit. #On branch master #Changes to be committed: #(use "git reset HEAD ..." to unstage) #new file: README #modified: benchmarks.rb ``` Вы можете видеть, что комментарий по умолчанию для коммита содержит закомментированный результат работы команды ``git status``. Вы можете удалить эти комментарии и набрать своё сообщение или же оставить их для напоминания о том, что вы фиксируете. (Для ещё более подробного напоминания, что же именно вы поменяли, можете передать аргумент ­v в команду ``git commit``. Это приведёт к тому, что в комментарий будет также помещена дельта/diff изменений, таким образом вы сможете точно увидеть всё, что сделано.) Когда вы выходите из редактора, Git создаёт для вас коммит с этим сообщением (удаляя комментарии и вывод diff'а). Есть и другой способ — вы можете набрать свой комментарий к коммиту в командной строке вместе с командой commit, указав его после параметра ­m, как в следующем примере: ``` git commit -­m "Story 182: Fix benchmarks for speed" [master]: created 463dc4f: "Fix benchmarks for speed" 2 files changed, 3 insertions(+), 0 deletions(­) create mode 100644 README ``` Итак, вы создали коммит! Вы можете видеть, что коммит вывел вам немного информации о себе: на какую ветку вы выполнили коммит (master), какая контрольная сумма SHA­1 у этого коммита (463dc4f), сколько файлов было изменено, а также статистику по добавленным/удалённым строкам в этом коммите. Запомните, что коммит сохраняет снимок состояния вашего индекса. Всё, что вы не проиндексировали, так и остается в рабочем каталоге как изменённое; вы можете сделать ещё один коммит, чтобы добавить эти изменения в репозиторий. Каждый раз, когда вы делаете коммит, вы сохраняете снимок состояния вашего проекта, который позже вы можете восстановить или с которым можно сравнить текущее состояние. #### Просмотр истории коммитов После того как вы создадите несколько коммитов, или же вы склонируете репозиторий с уже существующей историей коммитов, вы, вероятно, захотите оглянуться назад и узнать, что же происходило с этим репозиторием. Наиболее простой и в то же время мощный инструмент для этого — команда ``git log``. Данные примеры используют очень простой проект, названный simplegit. Чтобы получить этот проект, выполните: ``` git clone git://github.com/schacon/simplegit­progit.git ``` В результате выполнения ``git log`` в данном проекте, вы должны получить что­то вроде этого: ``` git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 ­0700 changed the version 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 ``` По умолчанию, без аргументов, ``git log`` выводит список коммитов созданных в данном репозитории в обратном хронологическом порядке. То есть самые последние коммиты показываются первыми. Как вы можете видеть, эта команда отображает каждый коммит вместе с его контрольной суммой SHA­1, именем и электронной почтой автора, датой создания и комментарием. Существует великое множество параметров команды ``git log`` и их комбинаций, для того чтобы показать вам именно то, что вы ищете. ### Отмена изменений На любой стадии может возникнуть необходимость что­либо отменить. Здесь мы рассмотрим несколько основных инструментов для отмены произведённых изменений. Будьте осторожны, ибо не всегда можно отменить сами отмены. Это одно из немногих мест в Git'е, где вы можете потерять свою работу если сделаете что­то неправильно. #### Изменение последнего коммита Одна из типичных отмен происходит тогда, когда вы делаете коммит слишком рано, забыв добавить какие­то файлы, или напутали с комментарием к коммиту. Если вам хотелось бы сделать этот коммит ещё раз, вы можете выполнить commit с опцией --­­amend: ``` git commit --­­amend ``` Эта команда берёт индекс и использует его для коммита. Если после последнего коммита не было никаких изменений (например, вы запустили приведённую команду сразу после предыдущего коммита), то состояние проекта будет абсолютно таким же и всё, что вы измените, это комментарий к коммиту. Появится всё тот же редактор для комментариев к коммитам, но уже с введённым комментарием к последнему коммиту. Вы можете отредактировать это сообщение так же, как обычно, и оно перепишет предыдущее. Для примера, если после совершения коммита вы осознали, что забыли проиндексировать изменения в файле, которые хотели добавить в этот коммит, вы можете сделать что­то подобное: ``` git commit -­m 'initial commit' git add forgotten_file git commit --­­amend ``` Все три команды вместе дают один коммит — второй коммит заменяет результат первого. ### Работа с удалёнными репозиториями >*Удаленный* тут надо понимать не как стертый (deleted) а как находящийся где-то в сети (remote) Чтобы иметь возможность совместной работы над каким­-либо Git-­проектом, необходимо знать, как управлять удалёнными репозиториями. Удалённые репозитории — это модификации проекта, которые хранятся в интернете или ещё где­-то в сети. Их может быть несколько, каждый из которых, как правило, доступен для вас либо только на чтение, либо на чтение и запись. Совместная работа включает в себя управление удалёнными репозиториями и помещение (push) и получение (pull) данных в и из них тогда, когда нужно обменяться результатами работы. Управление удалёнными репозиториями включает умение добавлять удалённые репозитории, удалять те из них, которые больше не действуют, умение управлять различными удалёнными ветками и определять их как отслеживаемые (tracked) или нет и прочее. Данный раздел охватывает все перечисленные навыки по управлению удалёнными репозиториями. Например, в рамках нашего курса вы можете дополнительно к git-серверу колледжа (GOGS) добавить личный репозиторий на github, чтобы иметь возможность доделать лабы дома. #### Отображение удалённых репозиториев Чтобы просмотреть, какие удалённые серверы у вас уже настроены, следует выполнить команду ``git remote``. Она перечисляет список имён-­сокращений для всех уже указанных удалённых дескрипторов. Если вы склонировали ваш репозиторий, у вас должен отобразиться, по крайней мере, **origin** — это имя по умолчанию, которое Git присваивает серверу, с которого вы склонировали: ``` git clone git://github.com/schacon/ticgit.git Initialized empty Git repository in /private/tmp/ticgit/.git/ remote: Counting objects: 595, done. remote: Compressing objects: 100% (269/269), done. remote: Total 595 (delta 255), reused 589 (delta 253) Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done. Resolving deltas: 100% (255/255), done. cd ticgit git remote origin ``` Чтобы посмотреть, какому URL соответствует сокращённое имя в Git, можно указать команде опцию ­``-v``: ``` git remote -­v origin git://github.com/schacon/ticgit.git (fetch) origin git://github.com/schacon/ticgit.git (push) ``` Если у вас больше одного удалённого репозитория, команда покажет их все. Например, мой репозиторий Grit выглядит следующим образом. ``` git remote -­v bakkdoor git://github.com/bakkdoor/grit.git cho45 git://github.com/cho45/grit.git defunkt git://github.com/defunkt/grit.git koke git://github.com/koke/grit.git origin git@github.com:mojombo/grit.git ``` Это означает, что мы легко можем получить изменения от любого из этих репозиториев. #### Добавление удалённых репозиториев В предыдущих разделах мы упомянули и немного продемонстрировали добавление удалённых репозиториев, сейчас мы рассмотрим это более детально. Чтобы добавить новый удалённый Git-­репозиторий под именем-­сокращением, к которому будет проще обращаться, выполните команду ``git remote add [сокращение] [url]``: ``` git remote origin git remote add pb git://github.com/paulboone/ticgit.git git remote -­v origin git://github.com/schacon/ticgit.git pb git://github.com/paulboone/ticgit.git ``` Теперь вы можете использовать в командной строке имя pb вместо полного URL. Например, если вы хотите извлечь (fetch) всю информацию, которая есть в репозитории Павла, но нет в вашем, вы можете выполнить ``git fetch pb``: ``` git fetch pb remote: Counting objects: 58, done. remote: Compressing objects: 100% (41/41), done. remote: Total 44 (delta 24), reused 1 (delta 0) Unpacking objects: 100% (44/44), done. From git://github.com/paulboone/ticgit * [new branch] master ­> pb/master * [new branch] ticgit ­> pb/ticgit ``` Ветка master Павла теперь доступна локально как pb/master. Вы можете слить (merge) её в одну из своих веток или перейти на эту ветку, если хотите её проверить. #### Fetch и Pull Как вы только что узнали, для получения данных из удалённых проектов, следует выполнить ``git fetch [имя удал. сервера]`` Данная команда связывается с указанным удалённым проектом и забирает все те данные проекта, которых у вас ещё нет. После того как вы выполнили команду, у вас должны появиться ссылки на все ветки из этого удалённого проекта. Теперь эти ветки в любой момент могут быть просмотрены или слиты. Когда вы клонируете репозиторий, команда clone автоматически добавляет этот удалённый репозиторий под именем origin. Таким образом, ``git fetch origin`` извлекает все наработки, отправленные (push) на этот сервер после того, как вы склонировали его (или получили изменения с помощью fetch). Важно отметить, что команда fetch забирает данные в ваш локальный репозиторий, но не сливает их с какими-­либо вашими наработками и не модифицирует то, над чем вы работаете в данный момент. Вам необходимо вручную слить эти данные с вашими, когда вы будете готовы. Если у вас есть ветка, настроенная на отслеживание удалённой ветки, то вы можете использовать команду ``git pull``. Она автоматически извлекает и затем сливает данные из удалённой ветки в вашу текущую ветку. Этот способ может для вас оказаться более простым или более удобным. К тому же по умолчанию команда ``git clone`` автоматически настраивает вашу локальную ветку master на отслеживание удалённой ветки master на сервере, с которого вы клонировали (подразумевается, что на удалённом сервере есть ветка master). Выполнение ``git pull``, как правило, извлекает (fetch) данные с сервера, с которого вы изначально склонировали, и автоматически пытается слить (merge) их с кодом, над которым вы в данный момент работаете. #### Push Когда вы хотите поделиться своими наработками, вам необходимо отправить (push) их в главный репозиторий. Команда для этого действия простая: ``git push [удал. сервер] [ветка]``. Чтобы отправить вашу ветку master на сервер origin (повторимся, что клонирование, как правило, настраивает оба этих имени автоматически), вы можете выполнить следующую команду для отправки наработок на сервер: ``` git push origin master ``` Эта команда срабатывает только в случае, если вы клонировали с сервера, на котором у вас есть права на запись, и если никто другой с тех пор не выполнял команду push. Если вы и кто-­то ещё одновременно клонируете, затем он выполняет команду push, а затем команду push выполняете вы, то ваш push точно будет отклонён. Вам придётся сначала вытянуть (pull) их изменения и объединить с вашими. Только после этого вам будет позволено выполнить push. #### Инспекция удалённого репозитория Если хотите получить побольше информации об одном из удалённых репозиториев, вы можете использовать команду ``git remote show [удал. сервер]``. Если вы выполните эту команду с некоторым именем, например, origin, вы получите что­то подобное: ``` git remote show origin * remote origin URL: git://github.com/schacon/ticgit.git Remote branch merged with 'git pull' while on branch master master Tracked remote branches master ticgit ``` Она выдаёт URL удалённого репозитория, а также информацию об отслеживаемых ветках. Эта команда любезно сообщает вам, что если вы, находясь на ветке master, выполните ``git pull``, ветка master с удалённого сервера будет автоматически влита в вашу сразу после получения всех необходимых данных. Она также выдаёт список всех полученных ею ссылок. Это был пример для простой ситуации, и наверняка вы встретились с чем-­то подобным. Однако, если вы используете Git более интенсивно, вы можете увидеть гораздо большее количество информации от ``git remote show``: ``` git remote show origin *remote origin URL: git@github.com:defunkt/github.git Remote branch merged with 'git pull' while on branch issues issues Remote branch merged with 'git pull' while on branch master master New remote branches (next fetch will store in remotes/origin) caching Stale tracking branches (use 'git remote prune') libwalker walker2 Tracked remote branches acl apiv2 dashboard2 issues master postgres Local branch pushed with 'git push' master:master ``` Данная команда показывает какая именно локальная ветка будет отправлена на удалённый сервер по умолчанию при выполнении ``git push``. Она также показывает, каких веток с удалённого сервера у вас ещё нет, какие ветки всё ещё есть у вас, но уже удалены на сервере. И для нескольких веток показано, какие удалённые ветки будут в них влиты при выполнении ``git pull``. #### Удаление и переименование удалённых репозиториев Для переименования ссылок в новых версиях Git'а можно вылолнить команду ``git remote rename``, это изменит сокращённое имя, используемое для удалённого репозитория. Например, если вы хотите переименовать pb в paul, вы можете сделать это следующим образом: ``` git remote rename pb paul git remote origin paul ``` Стоит упомянуть, что это также меняет для вас имена удалённых веток. То, к чему вы обращались как ``pb/master``, стало ``paul/master``. Если по какой­-то причине вы хотите удалить ссылку (вы сменили сервер или больше не используете определённое зеркало, или, возможно, контрибьютор перестал быть активным), вы можете использовать ``git remote rm``: ``` git remote rm paul git remote origin ``` ## Задания для самостоятельной работы Пройтись по пунктам 1-23 [этой][1] инструкции (до ветвлений) [содержание](/readme.md) [1]: https://githowto.com/ru/setup [_]: https://studfile.net/preview/6845207/ [_]: http://uii.mpei.ru/study/courses/sdt/16/lab02_vcs.task.pdf