Skip to content

Latest commit

 

History

History
410 lines (336 loc) · 26.5 KB

client-tfs.asc

File metadata and controls

410 lines (336 loc) · 26.5 KB

Git та TFS

Git популяризується серед Windows розробників і, якщо ви пишете код "під Windows", то є велика ймовірність, що ви також використовуєте Microsoft’s Team Foundation Server (TFS). TFS є набором інструментів для співпраці, що включає в себе облік дефектів, завдань, підтримку Scrum процесу та інших, перегляд коду, та контроль версій. Є трохи плутанини: TFS — це сервер, котрий має підтримку контролю коду, користуючись як Git, так і своєю власною СКВ, що має назву TFVC (Team Foundation Version Control). Підтримка Git є дещо новою особливістю для TFS (починаючи з 2013 версії), тому всі інструменти, що передували цій появі, звертаються до частини версіонування коду як ``TFS'', незважаючи на те, що насправді працюють з TFVC.

Якщо ви опинетеся в команді, котра користується TFVC, але краще б надали перевагу Git, як системі контролю версій, то для цього існує готовий проект.

Який інструмент

Насправді, їх є два: git-tf та git-tfs.

Git-tfs (можна знайти за https://github.com/git-tfs/git-tfs) є .NET проектом та (на момент написання цього тексту) сумісний тільки з Windows. Для роботи з Git сховищами він використовує .NET обгортку над libgit2, бібліотеко-орієнтованою реалізацією Git, що є високопродуктивною та дозволяє багато гнучкості з нутрощами Git сховища. Libgit2 не є повною реалізацією Git, тому git-tfs використовує клієнтську командну стрічку Git для того, щоб закрити недостачу, отже, фактично, немає обмежень в тому, що ця утиліта може робити зі сховищами Git. Її підтримка особливостей TFVC є достить зрілою через те, що вона оперує з сервером через бібліотеки Visual Studio. Це значить, що вам потрібен доступ до цих бібліотек, що, в свою чергу означає, що потрібно встановити недавню версію Visual Studio (будь-яку редакцію, починаючи з версії 2010, включно з Express починаючи з 2012), або Visual Studio SDK.

Git-tf (який живе за адресою https://gittf.codeplex.com) є Java проектом і через це може працювати на будь-якому комп’ютері з Java середовищем. Він взаємодіє з Git сховищем через JGit (JVM реалізація Git), тобто, практично не має обмежень щодо функціональності Git. Проте, робота TFVC не є повною, порівняно з git-tfs – немає підтримки гілок, для прикладу.

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

Note

Вам знадобиться доступ до сховища TFVC для того, щоб могти слідувати цим інструкціям. А їх не так просто знайти, як, скажімо, сховища Git чи Subversion, тому, можливо, прийдеться створити самому. Для цієї задачі добре підходять Codeplex (https://www.codeplex.com) чи Visual Studio Online (http://www.visualstudio.com).

Ознайомлення з git-tf

По-перше, як і з будь-яким іншим Git проектом, склонуймо. Ось як це виглядає з git-tf:

$ git tf clone https://tfs.codeplex.com:443/tfs/TFS13 $/myproject/Main project_git

Перший аргумент є URL до TFVC колекцій, другий має формат $/проект/гілка, а третій — це шлях до локального Git сховища, що буде створено (цей аргумент не обов’язковий). Git-tf може працювати лише з одною гілкою одночасно; якщо ви хочете зробити чекіни (checkins) до іншої гілки TFVC, то склонуйте заново з потрібної гілки.

Ось як створити повнофункціональний Git репозиторій:

$ cd project_git
$ git log --all --oneline --decorate
512e75a (HEAD, tag: TFS_C35190, origin_tfs/tfs, master) Checkin message

Це зветься мілким (shallow) клоном, в тому значенні, що завантажено лише найостанніший ченджсет. TFVC не спроектований таким чином, що кожен клієнт має повну копію історії, тому git-tf типово отримає лише останню версію, а це є значно швидшим.

Коли ж у вас вдосталь часу, мабуть, варто клонувати всю історію проекту, за допомогою опції --deep:

$ git tf clone https://tfs.codeplex.com:443/tfs/TFS13 $/myproject/Main \
  project_git --deep
Username: domain\user
Password:
Connecting to TFS...
Cloning $/myproject into /tmp/project_git: 100%, done.
Cloned 4 changesets. Cloned last changeset 35190 as d44b17a
$ cd project_git
$ git log --all --oneline --decorate
d44b17a (HEAD, tag: TFS_C35190, origin_tfs/tfs, master) Goodbye
126aa7b (tag: TFS_C35189)
8f77431 (tag: TFS_C35178) FIRST
0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \
        Team Project Creation Wizard

Зверніть увагу на теґи з іменами типу TFS_C35189; за допомогою цієї особливості ви дізнаєтеся який Git коміт та ченджсет TFVC пов’язані між собою. Це є хорошим відображенням, оскільки ви можете за допомогою простої команди log з’ясувати які з ваших комітів також також існують в TFVC. Ці теґи не є обов’язковими (і їх насправді можна вимкнути за допомогою git config git-tf.tag false) – git-tf все одно зберігає реальні зв’язки коміт-ченджсет у файлі .git/git-tf.

Ознайомлення з git-tfs

Клонування в git-tfs відбувається дещо інакше. Погляньте:

PS> git tfs clone --with-branches \
    https://username.visualstudio.com/DefaultCollection \
    $/project/Trunk project_git
Initialized empty Git repository in C:/Users/ben/project_git/.git/
C15 = b75da1aba1ffb359d00e85c52acb261e4586b0c9
C16 = c403405f4989d73a2c3c119e79021cb2104ce44a
Tfs branches found:
- $/tfvc-test/featureA
The name of the local branch will be : featureA
C17 = d202b53f67bde32171d5078968c644e562f1c439
C18 = 44cd729d8df868a8be20438fdeeefb961958b674

Зверніть увагу на прапорець --with-branches. Git-tfs має можливість створювати відповідності між гілками TFVC та Git, а цей прапорець вказує на необхідність створювати локальні Git гілки для кожної гілки TFVC. Його використання є рекомендованим якщо ви збираєтеся робити гілки чи зливати в TFS, проте такий підхід не працюватиме з сервером старішим за TFS 2010 – до цього релізу ``гілки'' були просто теками, тому git-tfs не міг відрізнити їх від звичайних тек.

Погляньте на результуюче Git сховище:

PS> git log --oneline --graph --decorate --all
* 44cd729 (tfs/featureA, featureA) Goodbye
* d202b53 Branched from $/tfvc-test/Trunk
* c403405 (HEAD, tfs/default, master) Hello
* b75da1a New project
PS> git log -1
commit c403405f4989d73a2c3c119e79021cb2104ce44a
Author: Ben Straub <ben@straub.cc>
Date:   Fri Aug 1 03:41:59 2014 +0000

    Hello

    git-tfs-id: [https://username.visualstudio.com/DefaultCollection]$/myproject/Trunk;C16

Маємо дві локальні гілки, master та featureA, котрі відображають стартову точку клонування (Trunk в іменуванні TFVC) та дочірню гілку (featureA в TFVC). Ви можете бачити також, що `віддалене сховище'' `tfs має також кілька посилань: default та featureA, які відображають гілки TFVC. Git-tfs робить відповідність між клонованою гілкою та tfs/default, а також інші отримують свої імена.

Ще варто звернути увагу на git-tfs-id: рядки в повідомленнях коміту. Замість теґів, git-tfs використовує ці позначки для зв’язку між TFVC ченджсетами та Git комітами. З цього випливає те, що ваші Git коміти матимуть різні SHA-1 хеші до та після надсилання до TFVC.

Процеси роботи Git-tf[s]
Note

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

$ git config set --local core.ignorecase=true
$ git config set --local core.autocrlf=false

Очевидно, далі ви б хотіли попрацювати над проектом. TFVC та TFS мають кілька особливостей що можуть ускладнити ваш робочий процес:

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

  2. Пам’ятайте, що TFVC дозволяє користувачам ``забирати''(checkout) файли з сервера, замикаючи їх так, що більш ніхто не зможе їх редагувати. Звичайно, це не є перепоною для роботою з цими файлами у вашому локальному сховищі, але може стати такою, коли прийде час надсилання змін до TFVC сервера.

  3. TFS має концепцію закритих'' ??? (gated'') чекінів, коли цикл побудова-тести має бути успішно завершеним до того, як дозволено робити чекін. Тут використовується функція відкладених комітів `shelve'' TFVC, яку ми тут детально не розглядатимемо. Ви можете сфабрикувати це вручну з git-tf та git-tfs котрі мають команду `checkintool, що знає про закриті чекіни.

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

Робочий процес git-tf

Скажімо, ви виконали деяку роботу, додали кілька комітів до master, а тепер готові ділитися своїми доробками на TFVC сервері. Ось наше Git сховище:

$ git log --oneline --graph --decorate --all
* 4178a82 (HEAD, master) update code
* 9df2ae3 update readme
* d44b17a (tag: TFS_C35190, origin_tfs/tfs) Goodbye
* 126aa7b (tag: TFS_C35189)
* 8f77431 (tag: TFS_C35178) FIRST
* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \
          Team Project Creation Wizard

Ми хочемо взяти відбиток коміту 4178a82 та надіслати його на TFVC сервер. Насамперед, подивимося чи хтось із колег долучався до проекту з того часу, як ми востаннє з’єднувалися:

$ git tf fetch
Username: domain\user
Password:
Connecting to TFS...
Fetching $/myproject at latest changeset: 100%, done.
Downloaded changeset 35320 as commit 8ef06a8. Updated FETCH_HEAD.
$ git log --oneline --graph --decorate --all
* 8ef06a8 (tag: TFS_C35320, origin_tfs/tfs) just some text
| * 4178a82 (HEAD, master) update code
| * 9df2ae3 update readme
|/
* d44b17a (tag: TFS_C35190) Goodbye
* 126aa7b (tag: TFS_C35189)
* 8f77431 (tag: TFS_C35178) FIRST
* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \
          Team Project Creation Wizard

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

  1. Зробити коміт злиття здається природнім для користувача Git (зрештою, git pull саме це й робить), а git-tf може це виконати за допомогою git tf pull. Однак, зауважте, що TFVC не мислить таким самим чином, і, якщо ви надсилаєте коміти злиття, ваша історія виглядатиме по-різному по обидві сторони, що може спантеличувати. Проте, якщо ви збираєтеся надіслати всі свої зміни як один ченджсет, це, мабуть, найлегший спосіб.

  2. Перебазовування робить історію лінійною, тобто дає нам можливість перетворити кожен Git коміт на ченджсет TFVC. Оскільки даний спосіб залишає нам найбільше можливостей потім, ми рекомендуємо саме його; git-tf підтримує цю дію за допомогою git tf pull --rebase.

Вибір за вами. У цьому прикладі ми перебазовуватимемо:

$ git rebase FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: update readme
Applying: update code
$ git log --oneline --graph --decorate --all
* 5a0e25e (HEAD, master) update code
* 6eb3eb5 update readme
* 8ef06a8 (tag: TFS_C35320, origin_tfs/tfs) just some text
* d44b17a (tag: TFS_C35190) Goodbye
* 126aa7b (tag: TFS_C35189)
* 8f77431 (tag: TFS_C35178) FIRST
* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \
          Team Project Creation Wizard

Тепер ми готові до чекіну в TFVC сервер. Git-tf дає можливість вибрати: створити один ченджсет, що представлятиме всі зміни, починаючи з останньої (--shallow, що є типовою поведінкою) чи створювати по ченджсету на кожен коміт (--deep). Тут ми просто створимо один ченджсет:

$ git tf checkin -m 'Updating readme and code'
Username: domain\user
Password:
Connecting to TFS...
Checking in to $/myproject: 100%, done.
Checked commit 5a0e25e in as changeset 35348
$ git log --oneline --graph --decorate --all
* 5a0e25e (HEAD, tag: TFS_C35348, origin_tfs/tfs, master) update code
* 6eb3eb5 update readme
* 8ef06a8 (tag: TFS_C35320) just some text
* d44b17a (tag: TFS_C35190) Goodbye
* 126aa7b (tag: TFS_C35189)
* 8f77431 (tag: TFS_C35178) FIRST
* 0745a25 (tag: TFS_C35177) Created team project folder $/tfvctest via the \
          Team Project Creation Wizard

Створився теґ TFS_C35348, вказуючи що TFVC має такий самий відбиток як відбиток в коміті 5a0e25e. Важливо зауважити, що не кожен Git коміт потребує точного відповідника в TFVC; коміт 6eb3eb5, наприклад, ніде не існує на сервері.

Таким є основний процес роботи. Ось ще кілька міркувань, що варто пам’ятати:

  • Робота з гілками не підтримується. Git-tf в змозі створити Git сховище лише з одної гілки TFVC одночасно.

  • Співпрацюйте за допомогою TFVC або Git, але не за допомогою обидвох. Різні git-tf клони одного й того ж TFVC сховища можуть мати різні SHA-1 хеші, що спричинить нескінченні головні болі.

  • Якщо процес вашої команди включає в себе роботу в Git та періодичні синхронізації до TFVC, з’єднуйте до TFVC лише одне Git сховище.

Робочий процес git-tfs

Пройдімо такий самий сценарій з git-tfs. Маємо нові коміти, зроблені в гілку master нашого Git сховища:

PS> git log --oneline --graph --all --decorate
* c3bd3ae (HEAD, master) update code
* d85e5a2 update readme
| * 44cd729 (tfs/featureA, featureA) Goodbye
| * d202b53 Branched from $/tfvc-test/Trunk
|/
* c403405 (tfs/default) Hello
* b75da1a New project

Тепер глянемо чи хтось додав якісь зміни, поки ми тут мудрували:

PS> git tfs fetch
C19 = aea74a0313de0a391940c999e51c5c15c381d91d
PS> git log --all --oneline --graph --decorate
* aea74a0 (tfs/default) update documentation
| * c3bd3ae (HEAD, master) update code
| * d85e5a2 update readme
|/
| * 44cd729 (tfs/featureA, featureA) Goodbye
| * d202b53 Branched from $/tfvc-test/Trunk
|/
* c403405 Hello
* b75da1a New project

Так, виявляється, що хтось із наших колег додав TFVC ченджсет, який ми бачимо як новий коміт aea74a0, а віддалена гілка tfs/default прогресувала.

Так само як і у випадку git-tf, ми маємо дві фундаментальні опції, щоб розв’язати цю розбіжність:

  1. Перебазуватися та зберегти історію лінійною.

  2. Виконати злиття та зберегти що ж насправді трапилося.

В нашому випадку ми робитимемо ``глибокий'' чекін, тобто кожен Git коміт стає ченджсетом TFVC, тому виберемо варіант з перебазовуванням.

PS> git rebase tfs/default
First, rewinding head to replay your work on top of it...
Applying: update readme
Applying: update code
PS> git log --all --oneline --graph --decorate
* 10a75ac (HEAD, master) update code
* 5cec4ab update readme
* aea74a0 (tfs/default) update documentation
| * 44cd729 (tfs/featureA, featureA) Goodbye
| * d202b53 Branched from $/tfvc-test/Trunk
|/
* c403405 Hello
* b75da1a New project

Тепер ми готові завершити наш вклад, зачекінивши код до TFVC серверу. Будемо використовувати команду rcheckin для того, щоб створювався TFVC ченджсет на кожен Git коміт від HEAD до першого віддаленого посилання tfs (команда checkin створила б просто один ченджсет, щось типу того як працює зчавлення (squashing) комітів).

PS> git tfs rcheckin
Working with tfs remote: default
Fetching changes from TFS to minimize possibility of late conflict...
Starting checkin of 5cec4ab4 'update readme'
 add README.md
C20 = 71a5ddce274c19f8fdc322b4f165d93d89121017
Done with 5cec4ab4b213c354341f66c80cd650ab98dcf1ed, rebasing tail onto new TFS-commit...
Rebase done successfully.
Starting checkin of b1bf0f99 'update code'
 edit .git\tfs\default\workspace\ConsoleApplication1/ConsoleApplication1/Program.cs
C21 = ff04e7c35dfbe6a8f94e782bf5e0031cee8d103b
Done with b1bf0f9977b2d48bad611ed4a03d3738df05ea5d, rebasing tail onto new TFS-commit...
Rebase done successfully.
No more to rcheckin.
PS> git log --all --oneline --graph --decorate
* ff04e7c (HEAD, tfs/default, master) update code
* 71a5ddc update readme
* aea74a0 update documentation
| * 44cd729 (tfs/featureA, featureA) Goodbye
| * d202b53 Branched from $/tfvc-test/Trunk
|/
* c403405 Hello
* b75da1a New project

Зверніть увагу на те, як після кожного успішного чекіна до TFVC сервера, git-tfs перебазовує залишкові зміни поверх щойно зробленого. Це тому, що додається поле git-tfs-id в кінці повідомлення коміту, і це змінює SHA-1 хеші. Так і було задумано, не потрібно хвилюватися з цього приводу, просто вам потрібно знати, що це відбувається; особливо, якщо ви ділитеся ідентифікаторами Git комітів з іншими.

TFS має багато особливостей для інтеграції зі своєю системою контролю версій, такі як одиниці роботи (work items), переглядальники коду, закриті (gated) чекіни тощо. Опанувати їх всіх з командного рядка може бути досить хвацькою задачею, але, на щастя, git-tfs має досить швидкий доступ і до більш візуальних інструментів чекіну:

PS> git tfs checkintool
PS> git tfs ct

Виглядає це якось так:

Інструмент чекіну git-tfs.
Figure 1. Інструмент чекіну git-tfs.

Це виглядатиме звичним для користувачів TFS, оскільки це той самий діалог, що запускається у Visual Studio.

Git-tfs також дає можливість керувати гілками TFVC з Git сховища. Для прикладу, створимо гілку:

PS> git tfs branch $/tfvc-test/featureBee
The name of the local branch will be : featureBee
C26 = 1d54865c397608c004a2cadce7296f5edc22a7e5
PS> git log --oneline --graph --decorate --all
* 1d54865 (tfs/featureBee) Creation branch $/myproject/featureBee
* ff04e7c (HEAD, tfs/default, master) update code
* 71a5ddc update readme
* aea74a0 update documentation
| * 44cd729 (tfs/featureA, featureA) Goodbye
| * d202b53 Branched from $/tfvc-test/Trunk
|/
* c403405 Hello
* b75da1a New project

Створення гілки в TFVC означає додавання ченджсету до гілки, що вже існує, і це відображено окремим комітом Git. Також, зверніть увагу, що git-tfs створив віддалену гілку tfs/featureBee, але HEAD досі вказує на master. Якщо вам кортить попрацювати з щойно створеною гілкою, потрібно базувати свої нові коміти на коміті 1d54865, можливо, створивши тематичну гілку з цього коміту.

Git та TFS. Підсумок

Обидві Git-tf та Git-tfs є чудовими інструментами для доступу до сервера TFVC та роботи з ним. Вони дають вам локальну могутність Git, уникають постійних мандрів мережею до центрального сервера TFVC, та спрощують ваше розробницьке життя, без необхідності переходу на Git цілою командою. Якщо ви працюєте з Windows (що дуже ймовірно, коли користуєтеся TFS), то вам, мабуть, більше захочеться обрати git-tfs, через більш повний набір особливостей, а у випадку іншої платформи, ви користуватиметеся git-tf, яка є більш обмеженою. Як і з більшістю інструментів цього розділу, вам потрібно обрати одну з систем контролю версій, яка буде основною, а іншу використовувати ніби підлеглу – будь це Git чи TFVC, потрібно обрати один центр для співпраці, не обидва.