Розділ 3. Все про клонування

У старих системах керування версіями стандартна операція для отримання файлів — це checkout. Ви отримуєте набір файлів в конкретному збереженому стані.

У Git та інших розподілених системах керування версіями стандартний спосіб — клонування. Для отримання файлів ви створюєте „клон“ всього сховища. Іншими словами, ви фактично створюєте дзеркало центрального сервера. При цьому все, що можна робити з основним сховищем, можна робити і з локальним.

Синхронізація комп'ютерів

Я терпимий до створення архівів або використання rsync для резервного копіювання і найпростішої синхронізації. Але я працюю то на ноутбуці, то на стаціонарному комп’ютері, які можуть ніяк між собою не взаємодіяти.

Створіть сховище Git і закоммітьте файли на одному комп'ютері. А потім виконайте на іншому

$ git clone перший.комп’ютер:/шлях/до/файлів

для створення другого примірника файлів і сховища Git. З цього моменту команди

$ git commit -a
$ git pull інший.комп’ютер:/шлях/до/файлів HEAD

будуть „втягувати“ („pull“) стан файлів з іншого комп'ютера на той, де ви працюєте. Якщо ви нещодавно внесли конфліктуючі зміни в один і той же файл, Git дасть вам знати, і потрібно буде зробити комміт заново після вирішення ситуації.

Класичне керування вихідним кодом

Створіть сховище Git для ваших файлів:

$ git init
$ git add .
$ git commit -m "Початковий комміт"

На центральному сервері створіть так зване „голе сховище“ („bare repository“) Git в деякому каталозі:

$ mkdir proj.git
$ cd proj.git
$ git --bare init
$ touch proj.git/git-daemon-export-ok

Запустіть Git-демон, якщо необхідно:

$ git daemon --detach # можливо вже запущений

Для створення нового порожнього сховища Git на публічних серверах виконуйте їх інструкції. Зазвичай, потрібно заповнити форму на веб-сторінці.

Відправте ваші зміни в центральне сховище ось так:

$ git push git://центральний.сервер/шлях/до/proj.git HEAD

Для отримання ваших вихідних кодів розробник вводить

$ git clone git://центральний.сервер/шлях/до/proj.git

Після внесення змін розробник зберігає зміни локально:

$ git commit -a

Для оновлення до останньої версії:

$ git pull

Будь-які конфлікти злиття потрібно дозволити і закоммітити:

$ git commit -a

Для вивантаження локальних змін в центральне сховище:

$ git push

Якщо на головному сервері були нові зміни, зроблені іншими розробниками, команда push не спрацює. У цьому випадку розробнику потрібно буде витягнути до себе (pull) останню версію, вирішити можливі конфлікти зливань і спробувати ще раз.

Розробники повинні мати SSH доступ для зазначених вище команд вивантаження та витягування (push та pull). Тим не менш, будь-хто може бачити джерело, набравши:

$ git clone git://центральний.сервер/шлях/до/proj.git

Власний протокол Git подібний до HTTP: немає аутентифікації, так що кожен може отримати проект. Відповідно, за замовчуванням, вивантаження заборонене через протокол Git.

Таємне джерело (Secret Source)

Для проектів із закритим вихідним кодом опустіть команди доступу і переконайтеся, що ви ніколи не створювали файл з ім'ям git-daemon-export-ok. Сховище вже не може бути доступним через протокол Git; тільки ті, хто має доступ SSH можуть побачити його. Якщо всі ваші репозиторії закриті, немає необхідності запускати демон Git оскільки всі зв’язки відбувається через SSH.

Голі сховища (Bare repositories)

Голе сховище називається так тому, що у нього немає робочого каталогу. Воно містить лише файли, які зазвичай приховані в підкаталозі .git. Іншими словами, голе сховище містить історію змін, але не містить знімка якоїсь певної версії.

Голе сховище грає роль, схожу на роль основного сервера в централізованій системі керування версіями: це дім вашого проекту. Розробники клонують з нього проект і закачують в нього свіжі офіційні зміни. Як правило, воно розташовується на сервері, який не робить майже нічого окрім роздачі даних. Розробка йде в клонах, тому домашнє сховище може обійтися і без робочого каталогу.

Багато команд Git не працюють в голих сховищах, якщо змінна середовища GIT_DIR не містить шлях до сховища та не зазначений параметр --bare.

Push чи pull?

Навіщо вводиться команда push, замість використання вже знайомої pull? Перш за все, pull не працює в голих сховищах, замість неї потрібно використовувати команду fetch, яка буде розглянута пізніше. Але навіть якщо тримати на центральному сервері нормальне сховище, використання команди pull в ньому буде складним . Потрібно буде спочатку увійти на сервер інтерактивно і повідомити команді pull адресу машини, з якої ми хочемо забрати зміни. Цьому можуть заважати мережеві брандмауери (firewall), але в першу чергу: що якщо в нас немає інтерактивного доступу до сервера?

Тим не менш, не рекомендутся push-ити в сховище крім цього випадку — через плутанину, яка може виникнути, якщо у цільового сховища є робочий каталог.

Коротше кажучи, поки вивчаєте Git, push-те лише в голі сховища. В інших випадках pull-те.

Розгалуження проекту

Не подобається шлях розвитку проекту? Думаєте, можете зробити краще? Тоді на своєму сервері виконайте

$ git clone git://основний.сервер/шлях/до/файлів

Тепер розкажіть усім про вітку проекту на вашому сервері.

Пізніше ви зможете в будь-який момент втягнути до себе зміни з початкового проекту:

$ git pull

Максимальні бекапи

Хочете мати безліч захищених, географічно відокремлених запасних архівів? Якщо у вашому проекті багато розробників, нічого робити не потрібно! Кожен клон — це і є резервна копія, не тільки поточного стану, але і всієї історії змін проекту. Завдяки криптографічному хешування, пошкодження якого-небудь з клонів буде виявлено при першій же спробі взаємодії з іншими клонами.

Якщо ваш проект не такий популярний, знайдіть якомога більше серверів для розміщення клонів.

Тим, хто особливо турбується, рекомендується завжди записувати останній 20-байтний SHA1 хеш HEAD у якомусь безпечному місці. Воно має бути безпечним, а не таємним. Наприклад, хороший варіант — публікація в газеті, тому що атакуючому складно змінити кожен примірник газети.

Багатозадачність зі швидкістю світла

Скажімо, ви хочете працювати над декількома функціями паралельно. Тоді закоммітьте ваші зміни і запустіть

$ git clone . /якийсь/новий/каталог

Завдяки жорстким посиланням, створення локального клону вимагає менше часу і місця, ніж просте копіювання.

Тепер ви можете працювати з двома незалежними функціями одночасно. Наприклад, можна редагувати один клон, поки інший компілюється. У будь-який момент можна зробити комміт і витягнути зміни з іншого клону:

$ git pull /другий/клон HEAD

Партизанське керування версіями

Ви працюєте над проектом, який використовує іншу систему керування версіями, і вам дуже не вистачає Git? Тоді створіть сховище Git у своєму робочому каталозі:

$ git init
$ git add .
$ git commit -m "Початковий комміт"

потім склонуйте його:

$ git clone . /якийсь/новий/каталог

Тепер перейдіть в цей новий каталог і працюйте в ньому замість основного, використовуючи Git в своє задоволення. У якийсь момент вам знадобитися синхронізувати зміни з усіма іншими — тоді перейдіть в початковий каталог, синхронізуйте його за допомогою іншої системи керування версіями і наберіть

$ git add .
$ git commit -m "Синхронізація з рештою"

Тепер перейдіть в новий каталог і запустіть

$ git commit -a -m "Опис моїх змін"
$ git pull

Процедура передачі змін іншим залежить від іншої системи керування версіями. Новий каталог містить файли з вашими змінами. Запустіть команди іншої системи керування версіями, необхідні для завантаження файлів в центральне сховище.

Subversion (імовірно, найкраща централізована система керування версіями) використовується незліченною кількістю проектів. Команда git svn автоматизує описаний процес для сховищ Subversion, а також може бути використана для експорту проекту Git в сховище Subversion.

Mercurial

Mercurial — схожа система керування версіями, яка може працювати в парі з Git практично без накладок. З розширенням hg-git користувач Mercurial може без будь-яких втрат push-ити і pull-ити зі сховища Git.

Отримати hg-git можна за допомогою Git:

$ git clone git://github.com/schacon/hg-git.git

або Mercurial:

$ hg clone http://bitbucket.org/durin42/hg-git/

На жаль, мені невідоме аналогічне розширення для Git. Тому я рекомендую використовувати Git, а не Mercurial, для центрального сховища, навіть якщо ви віддаєте перевагу Mercurial. Для проектів, що використовують Mercurial, зазвичай який-небудь доброволець підтримує паралельне сховище Git для залучення користувачів останнього, тоді як проекти, що використовують Git, завдяки hg-git автоматично доступні користувачам Mercurial.

Хоча розширення може конвертувати сховище Mercurial в Git шляхом push'а в порожнє сховище, цю задачу легше вирішити, використовуючи сценарій hg-fast-export.sh, доступний з

$ git clone git://repo.or.cz/fast-export.git

Для перетворення виконайте в порожньому каталозі

$ git init
$ hg-fast-export.sh -r /hg/repo

після додавання сценарію в ваш $PATH.

Bazaar

Згадаємо коротко Bazaar, оскільки це найпопулярніша вільна розподілена система керування версіями після Git і Mercurial.

Bazaar відносно молодий, тому у нього є перевага ідущого слідом. Його проектувальники можуть вчитися на помилках попередників і позбутися від історично сформованих недоліків. Крім того, його розробники піклуються про переносимість і взаємодії з іншими системами керування версіями.

Розширення bzr-git дозволяє (в якійсь мірі) користувачам Bazaar працювати зі сховищами Git. Програма tailor конвертує сховища Bazaar в Git і може робити це з накопиченням, тоді як bzr-fast-export добре пристосована для разових перетворень.

Чому я використовую Git

Спочатку я вибрав Git тому, що чув, що він в змозі впоратися з абсолютно некерованими вихідними текстами ядра Linux. Я ніколи не відчував потреби змінити його на щось інше. Git працює чудово і мені ще тільки належить напоротися на його недоліки. Так як я в основному використовую Linux, проблеми на інших системах мене не стосуються.

Я також віддаю перевагу програмам на C і сценаріям на bash у порівнянні з виконуваними файлами на зразок сценаріїв на Python-і: у них менше залежностей і я звик до швидкого виконання.

Я думав про те, як можна поліпшити Git, аж до того, щоб написати власний інструмент, схожий на Git; але лише як академічну вправу. Завершивши проект, я б всеодно продовжив користуватися Git, тому що виграш занадто малий, щоб виправдати використання саморобної системи.

Природньо, що ваші потреби та побажання імовірно відрізняються від моїх і ви, можливо, краще уживетеся з іншою системою. І все ж ви не занадто помилитеся, використовуючи Git.