Git se está volviendo popular entre los desarrolladores de Windows, y si estás escribiendo códigos en Windows, hay muchas posibilidades de que estés usando Team Foundation Server (TFS) de Microsoft. TFS es un paquete de colaboración que incluye seguimiento de defectos y elementos de trabajo, soporte de procesos para Scrum y otros, revisión de código y control de versiones. Hay un poco de confusión por delante: * TFS * es el servidor, que admite controlar el código fuente utilizando tanto Git como su propio VCS personalizado, al que han denominado * TFVC * (Team Foundation Version Control). El soporte de Git es una característica algo nueva para TFS (envío con la versión de 2013), por lo que todas las herramientas anteriores a eso se refieren a la porción de control de versión como `` TFS '', aunque en su mayoría funcionan con TFVC.
Si te encuentras en un equipo que usa TFVC pero prefieres usar Git como su cliente de control de versiones, hay un proyecto para ti.
De hecho, hay dos: git-tf
y git-tfs
.
git-tfs
(alojado en https://github.com/git-tfs/git-tfs []) es un proyecto .NET, y (al momento de escribir esto) solo se ejecuta en Windows.
Para trabajar con repositorios Git, utiliza los enlaces .NET para 'libgit2', una implementación de Git orientada a la biblioteca que es altamente eficiente y permite mucha flexibilidad con las agallas de un repositorio Git.
'Libgit2' no es una implementación completa de Git, por lo que para cubrir la diferencia, git-tfs
realmente llamará al cliente Git de la línea de comandos para algunas operaciones, por lo que no hay límites artificiales sobre lo que puede hacer con los repositorios Git.
Su compatibilidad con las características de TFVC es muy madura, ya que utiliza los ensamblados de Visual Studio para operaciones con servidores.
Esto significa que necesitará acceso a esos ensamblados, lo que significa que necesita instalar una versión reciente de Visual Studio (cualquier edición desde la versión 2010, incluido Express desde la versión 2012) o el SDK de Visual Studio.
git-tf
(cuyo alojamiento se encuentra en https://gittf.codeplex.com []) es un proyecto de Java y, como tal, se ejecuta en cualquier computadora con un entorno de tiempo de ejecución de Java.
Interactúa con los repositorios de Git a través de 'JGit' (una implementación JVM de Git), lo que significa que prácticamente no tiene limitaciones en términos de funciones de Git.
Sin embargo, su soporte para TFVC es limitado en comparación con git-tfs
. Por ejemplo, no admite ramas.
Entonces, cada herramienta tiene ventajas y desventajas, y hay muchas situaciones que favorecen a una sobre la otra. Cubriremos el uso básico de ambas en este libro.
Note
|
Necesitará acceder a un repositorio basado en TFVC para seguir estas instrucciones. Estos no son tan abundantes en la naturaleza como los repositorios de Git o Subversion, por lo que puede necesitar crear uno propio. Codeplex (https://www.codeplex.com []) o Visual Studio Online (http://www.visualstudio.com []) son buenas opciones para esto. |
Lo primero que haces, al igual que con cualquier proyecto de Git, es clonar.
Esto es lo que parece con git-tf
:
$ git tf clone https://tfs.codeplex.com:443/tfs/TFS13 $/myproject/Main project_git
El primer argumento es la URL de una colección TFVC, el segundo es de la forma $ / project / branch
, y el tercero es la ruta al repositorio Git local que se va a crear (este último es opcional).
git-tf
sólo puede funcionar con una rama a la vez; si quieres hacer 'checkins' en una rama diferente de TFVC, tendrás que hacer un nuevo clon desde esa rama.
Esto crea un repositorio de Git completamente funcional:
$ cd project_git
$ git log --all --oneline --decorate
512e75a (HEAD, tag: TFS_C35190, origin_tfs/tfs, master) Checkin message
Esto se denomina clon shallow, lo que significa que sólo se ha descargado el último conjunto de cambios.
TFVC no está diseñado para que cada cliente tenga una copia completa del historial, por lo que git-tf
usa de manera predeterminada la última versión, que es mucho más rápida.
Si tienes algo de tiempo, probablemente valga la pena clonar todo el historial del proyecto, usando la opción --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
Observa las etiquetas con nombres como TFS_C35189
; esta es una característica que te ayuda a saber qué compromisos de Git están asociados con los conjuntos de cambios de TFVC.
Esta es una buena forma de representarlo, ya que puedes ver con un comando de registro simple cuál de tus confirmaciones está asociada con una instantánea que también existe en TFVC.
No son necesarios (y, de hecho, puedes desactivarlos con git config git-tf.tag false
) - git-tf
conserva las asignaciones reales 'commit-changeset' en el archivo .git / git-tf
.
La clonación de git-tfs
se comporta de forma un poco diferente.
Observe:
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
Observa el indicador --with-branches
.
git-tfs
es capaz de mapear ramas de TFVC a ramas de Git, y este indicador le dice que configure una rama local de Git para cada rama de TFVC.
Esto es muy recomendable si alguna vez se ha bifurcado o se ha fusionado en TFS, pero no funcionará con un servidor anterior a TFS 2010; antes de esa versión, `` branches '' eran sólo carpetas, por lo que `git-tfs no puede hacer esto con las carpetas regulares.
Echemos un vistazo al repositorio Git resultante:
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
Hay dos ramas locales, master
y` featuresS`, que representan el punto inicial del clon (Trunk
en TFVC) y una rama secundaria (` featureS` en TFVC).
También puedes ver que el tfs`
remote '' también tiene un par de referencias: `default
y featureA
, que representan las ramas de TFVC.
git-tfs
mapea la rama desde la que clonaste a tfs / default
, y otras obtienen sus propios nombres.
Otra cosa a notar es las líneas git-tfs-id:
en los mensajes de confirmación.
En lugar de etiquetas, git-tfs
usa estos marcadores para relacionar los conjuntos de cambios de TFVC con las confirmaciones de Git.
Esto tiene la consecuencia de que tus confirmaciones de Git tendrán un hash SHA-1 diferente antes y después de que se hayan enviado a TFVC.
Note
|
Independientemente de la herramienta que estés utilizando, debes establecer un par de valores de configuración de Git para evitar problemas. $ git config set --local core.ignorecase=true
$ git config set --local core.autocrlf=false |
Lo siguiente que querrás hacer es trabajar en el proyecto. TFVC y TFS tienen varias características que pueden agregar complejidad a tu flujo de trabajo:
-
Las ramas de características que no están representadas en TFVC agregan un poco de complejidad. Esto tiene que ver con las * muy * diferentes formas en que TFVC y Git representan las ramas.
-
Ten en cuenta que TFVC permite a los usuarios "verificar" los archivos del servidor, bloqueándolos para que nadie más pueda editarlos. Obviamente, esto no te impedirá editarlos en tu repositorio local, pero podría interferir cuando llegue el momento de enviar tus cambios al servidor TFVC.
-
TFS tiene el concepto de comprobaciones "compuertas", donde un ciclo de prueba de compilación TFS debe completarse satisfactoriamente antes de permitir el registro. Utiliza la función
` shelve '' en TFVC, que no cubrimos en detalle aquí. Puedes falsificar esto de forma manual con `git-tf
, ygit-tfs
proporciona el comandocheckintool
que es sensible a la puerta.
En aras de la brevedad, lo que trataremos aquí es el camino feliz, qué pasos laterales seguir para evitar la mayoría de estos problemas.
Digamos que has hecho algo de trabajo, has hecho un par de confirmaciones de Git en master
y estás listo para compartir tu progreso en el servidor de TFVC.
Aquí está nuestro repositorio de 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
Queremos tomar la instantánea que está en la confirmación 4178a82
y subirla al servidor TFVC.
Lo primero es lo primero: veamos si alguno de nuestros compañeros de equipo hizo algo desde la última vez que nos conectamos:
$ 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
Parece que alguien más está trabajando también, y ahora tenemos una historia divergente. Aquí es donde brilla Git, pero tenemos dos opciones de cómo proceder:
-
Hacer una confirmación de fusión se siente natural como un usuario de Git (después de todo, eso es lo que hace
git pull
), ygit-tf
puede hacer esto por ti con un simplegit tf pull
. Ten en cuenta, sin embargo, que TFVC no piensa de esta manera, y si empujas la fusión se comprometerá y tu historia comenzará a verse diferente en ambos lados, lo que puede ser confuso. Sin embargo, si planeas enviar todos tus cambios como un solo conjunto de cambios, esta es probablemente la opción más fácil. -
'Rebasing' hace que nuestro historial de compromisos sea lineal, lo que significa que tenemos la opción de convertir cada una de nuestras confirmaciones de Git en un conjunto de cambios de TFVC. Como esto deja la mayoría de las opciones abiertas, te recomendamos que lo hagas de esta manera;
git-tf
incluso te lo facilita congit tf pull --rebase
.
La decisión es tuya: Para este ejemplo, vamos a rebasar:
$ 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
Ahora estamos listos para hacer una comprobación en el servidor de TFVC.
git-tf
te da la opción de hacer un único conjunto de cambios que represente todos los cambios desde el último (--shallow
, que es el predeterminado) y crear un nuevo conjunto de cambios para cada confirmación de Git (` --deep`).
Para este ejemplo, crearemos un solo conjunto de cambios:
$ 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
Hay una nueva etiqueta TFS_C35348
, que indica que TFVC está almacenando la misma instantánea exacta que la confirmación` 5a0e25e`.
Es importante tener en cuenta que no todas las confirmaciones de Git deben tener una contraparte exacta en TFVC; el compromiso 6eb3eb5
, por ejemplo, no existe en ninguna parte del servidor.
Ese es el flujo de trabajo principal. Hay un par de otras consideraciones que querrás tener en cuenta:
-
No hay ramificación.
git-tf
sólo puede crear repositorios Git de una rama TFVC a la vez. -
Colabora con TFVC o Git, pero no con ambos. Los diferentes clones de `ngit-tf`n del mismo repositorio de TFVC pueden tener diferentes hash de confirmación de SHA-1, lo que provocará innumerables dolores de cabeza.
-
Si el flujo de trabajo de tu equipo incluye la colaboración en Git y la sincronización periódica con TFVC, solo conéctate a TFVC con uno de los repositorios de Git.
Veamos el mismo escenario usando git-tfs
.
Aquí están las nuevas confirmaciones que hemos realizado en la rama master
en nuestro repositorio de 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
Ahora veamos si alguien más ha hecho un trabajo mientras estábamos hackeando:
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
Sí, resulta que nuestro compañero de trabajo ha agregado un nuevo conjunto de cambios de TFVC, que se muestra como el nuevo compromiso aea74a0
, y la rama remota tfs / default
se ha movido.
Al igual que con git-tf
, tenemos dos opciones fundamentales sobre cómo resolver esta historia divergente:
-
Rebase para preservar una historia lineal.
-
Fusión para preservar lo que realmente sucedió.
En este caso, haremos un ''checkin profundo '', donde cada confirmación de Git se convierte en un conjunto de cambios de TFVC, por lo que queremos volver a establecer la base.
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
Ahora estamos listos para completar nuestra contribución al registrar nuestro código en el servidor TFVC.
Usaremos el comando rcheckin
aquí para crear un conjunto de cambios TFVC para cada commit
de Git en la ruta de HEAD
a la primera rama remota tfs
encontrada (el comando checkin
sólo crearía un conjunto de cambios, más o menos como aplastar cuando Git se compromete).
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
Observa cómo después de cada registro exitoso en el servidor TFVC, git-tfs
vuelve a basar el trabajo restante en lo que acaba de hacer.
Esto se debe a que está agregando el campo git-tfs-id
al final de los mensajes de confirmación, lo que cambia los valores hash SHA-1.
Esto es exactamente como se diseñó, y no hay nada de qué preocuparse, pero debes saber que está sucediendo, especialmente si compartes 'commits' con otros.
TFS tiene muchas características que se integran con tu sistema de control de versiones, como elementos de trabajo, revisores designados, registros bloqueados, etc.
Puede ser engorroso trabajar con estas características usando sólo una herramienta de línea de comandos, pero afortunadamente git-tfs
te permite iniciar una herramienta gráfica de registro muy fácilmente:
PS> git tfs checkintool
PS> git tfs ct
Se parece un poco a esto:
Esto resultará familiar para los usuarios de TFS, ya que es el mismo diálogo que se inicia desde Visual Studio.
git-tfs
también te permite controlar ramas de TFVC desde tu repositorio de Git.
Como ejemplo, creemos una:
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
Crear una rama en TFVC significa agregar un conjunto de cambios donde esa rama ahora existe, y esto se proyecta como una confirmación de Git.
Ten en cuenta que git-tfs
también creó la rama remota tfs / featureBee
, pero` HEAD` todavía apunta a master
.
Si deseas trabajar en la rama recién acuñada, querrás basar tus nuevas confirmaciones en la confirmación 1d54865
, tal vez creando una rama de tema a partir de esa confirmación.
git-tf
y git-tfs
son excelentes herramientas para interactuar con un servidor TFVC.
Te permiten usar el poder de Git localmente, evitar tener que realizar un viaje de ida y vuelta al servidor central de TFVC, haciendo que tu vida como desarrollador sea mucho más fácil, sin forzar a todo tu equipo a migrar a Git.
Si estás trabajando en Windows (lo cual es probable si tu equipo está usando TFS), quizás quieras usar git-tfs
, ya que su conjunto de características es más completo, pero si estás trabajando en otra plataforma, puedes usar git-tf
, aunque es más limitado.
Al igual que con la mayoría de las herramientas de este capítulo, debes elegir uno de estos sistemas de control de versiones para que sea canónico y usar el otro de forma subordinada: Git o TFVC deberían ser el centro de colaboración, pero no ambos.