git perforce

Git para usuarios de Perforce



(5)

Esto no responde a su pregunta específicamente, pero no sé si sabe que una versión de forzosa de 2 usuarios y 5 áreas de trabajo se puede descargar y usar de forma gratuita desde el sitio web forzado .

De esta forma, puede usar forzosamente en casa para sus proyectos personales si lo desea. La única molestia son los 5 espacios de trabajo que pueden ser un poco limitantes, pero es bastante increíble tener forzosamente disponible para uso doméstico.

He estado usando Perforce durante varios años. Me gustaría cambiar a usar git para mi código personal, pero todos los tutoriales de git que he visto suponen que tienes un control de fuente n00b completo (lo que los hace increíblemente tediosos) o que estás acostumbrado a svn (que no soy)

Sé p4, y también entiendo la idea detrás de un sistema de control de fuente distribuido (así que no necesito un argumento de venta, gracias). Lo que me gustaría es una tabla de traducción del comando p4 a los comandos equivalentes de git, así como los comandos "no se puede vivir sin" que no tienen equivalente en p4.

Como sospecho que cada usuario de p4 usa un subconjunto diferente de p4, aquí hay algunas de las cosas que hago regularmente en p4 que me gustaría poder hacer en git que no son inmediatamente obvias de los documentos que he visto. :

  1. crear múltiples listas de cambios pendientes en un solo cliente. ( p4 change )
  2. edita una lista de cambios pendiente. (también p4 change )
  3. ver una lista de todas mis listas de p4 changes -s pending ( p4 changes -s pending )
  4. lista de todos los archivos modificados en mi cliente ( p4 opened ) o en una lista de cambios pendiente ( p4 describe )
  5. ver un diff de una lista de cambios pendiente (uso un script de envoltura para esto que usa p4 diff y p4 describe )
  6. para un archivo dado, vea qué listas de cambios enviadas afectaron qué líneas ( p4 annotate )
  7. para un archivo dado, vea una lista de las descripciones de las listas de cambios que afectaron el archivo ( p4 log )
  8. enviar una lista de cambios pendiente ( p4 submit -c )
  9. abortar una lista de cambios pendiente ( p4 revert )

Muchos de estos giran en torno a "listas de cambio". "lista de cambios" es la terminología p4. ¿Cuál es el término equivalente de git?

Parece que las sucursales pueden ser lo que los usuarios de git utilizan en lugar de lo que p4 llama listas de cambio. Un poco confuso, ya que p4 también tiene algo llamado rama, aunque parecen ser conceptos vagamente relacionados. (Aunque siempre pensé que el concepto de una rama de p4 era bastante extraño, es diferente una vez más del concepto clásico de RCS de una sucursal).

De todos modos ... No estoy seguro de cómo lograr lo que normalmente hago en las listas de cambios de p4 con las ramas de git. En p4 puedo hacer algo como esto:

$ p4 edit a.txt $ p4 change a.txt Change 12345 created.

En este punto, tengo un changlist que contiene a.txt. Puedo editar la descripción y continuar trabajando sin enviar la lista de cambios. Además, si resulta que necesito hacer algunos cambios en algunos otros archivos, como decir una corrección de error en alguna otra capa del código, puedo hacerlo en el mismo cliente:

$ p4 edit z.txt $ p4 change z.txt Change 12346 created.

Ahora tengo dos listas de cambios separadas en el mismo cliente. Puedo trabajar en estos simultáneamente, y no necesito hacer nada para "cambiar entre ellos". Cuando llega el momento de comprometerme, puedo enviarlos por separado:

$ p4 submit -c 12346 # this will submit the changes to z.txt $ p4 submit -c 12345 # this will submit the changes to a.txt

No puedo entender cómo replicar esto en git. De mis experimentos, no parece que git add esté asociado con la rama actual. Por lo que puedo decir, cuando git commit va a enviar todos los archivos que agregué, sin importar en qué rama estuve en ese momento:

$ git init Initialized empty Git repository in /home/laurence/git-playground/.git/ $ ls a.txt w.txt z.txt $ git add -A . $ git commit Initial commit. 3 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 a.txt create mode 100644 w.txt create mode 100644 z.txt $ vi a.txt z.txt 2 files to edit $ git status # On branch master # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: a.txt # modified: z.txt # no changes added to commit (use "git add" and/or "git commit -a") $ git branch aardvark $ git checkout aardvark M a.txt M z.txt Switched to branch ''aardvark'' $ git add a.txt $ git checkout master M a.txt M z.txt Switched to branch ''master'' $ git branch zebra $ git checkout zebra M a.txt M z.txt Switched to branch ''zebra'' $ git add z.txt $ git status # On branch zebra # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: a.txt # modified: z.txt # $ git checkout aardvark M a.txt M z.txt Switched to branch ''aardvark'' $ git status # On branch aardvark # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: a.txt # modified: z.txt

En este ejemplo, las ramas cebra y aardvark parecen contener exactamente el mismo conjunto de cambios, y en función del resultado del git status de git status , parece que hacer una confirmación en cualquiera de ellos tendrá el mismo efecto. ¿Estoy haciendo algo mal?


Hay una alternativa más ligera en git que podría formar parte de su flujo de trabajo; usando el área de preparación de git.

A menudo solo hago cambios y luego los envio, ya que varios commits (por ejemplo, agregar declaraciones de depuración, refactor, de hecho, arreglar un error). En lugar de configurar las listas de cambios obligatorias, realizar cambios y luego enviarlos, puede hacer los cambios y luego elegir cómo enviarlos (de manera opcional, utilizando el área de transición de git).

Puede enviar archivos particulares desde la línea de comando con:

git commit a.txt git commit z.txt

O organizando explícitamente los archivos primero:

git add a.txt git commit git add z.txt git commit

git gui te permitirá seleccionar líneas o trozos dentro de los archivos para crear una confirmación en el área de preparación. Esto es muy útil si tiene cambios en un archivo que desea tener en diferentes confirmaciones. Habiendo pasado de git a forzado y esto es algo que echo de menos.

Hay una pequeña advertencia a tener en cuenta con este flujo de trabajo. Si realiza los cambios A y B en un archivo, pruebe el archivo y luego confirme A, entonces no ha probado esa confirmación (independientemente de B).


No he utilizado mucho, por lo que puede no ser exactamente una traducción 1: 1. Entonces nuevamente los sistemas distribuidos de control de fuente como git y mercurial tienen un flujo de trabajo diferente de todos modos así que realmente no hay (y no debería haber) una traducción 1: 1. De todos modos, aquí va:

  • Crea múltiples listas de cambios pendientes -> Usa ramas en su lugar. En git, las ramas son livianas y rápidas, tarda menos de un segundo en crearse y, por lo general, menos de dos segundos en fusionarse. No tengas miedo de ramificar y rebase a menudo.

    git branch new-branch-name git checkout new-branch-name

    O hazlo todo en una sola línea:

    git checkout -b new-branch-name

  • Vea una lista de todas las listas de cambios pendientes -> Dado que el equivalente de múltiples listas de cambios pendientes es de múltiples ramas, simplemente vea las ramas:

    git branch

    Si quieres ver las sucursales remotas también:

    git branch -a

    Se considera una buena práctica eliminar inmediatamente una rama después de una fusión exitosa, por lo que no es necesario realizar un seguimiento de qué rama está pendiente fusionar y cuáles ya se han fusionado.

  • Listar todos los archivos modificados -> Para una sola "lista de cambios" pendiente en una rama específica, git tiene un concepto del índice o caché. Para comprometer un cambio, primero debe agregar archivos a este índice. Esto le permite seleccionar manualmente qué grupo de archivos representa un solo cambio o ignorar archivos irrelevantes. Para ver el estado de qué archivos se agregan, o no a este índice, simplemente hazlo:

    git status

  • Ver un diff de una lista de cambios pendiente -> Hay dos partes para esto. Primero, para ver una diferencia entre el directorio de trabajo y el índice:

    git diff

    Pero si quieres saber la diferencia entre lo que estás escribiendo ahora y la última confirmación, entonces realmente estás pidiendo una diferencia entre el directorio de trabajo + índice y HEAD:

    git diff HEAD

  • Para un archivo dado, vea qué listas de cambios enviadas afectaron qué líneas -> Esto es fácil:

    git blame filename

    o incluso mejor, si se encuentra en un entorno de ventanas:

    git gui blame filename

    Git gui tarda más tiempo en analizar el archivo (estaba escrito en tcl en lugar de C) pero tiene muchas características interesantes, incluida la capacidad de "viajar en el tiempo" atrás haciendo clic en una identificación de confirmación. Solo desearía que implementaran una función para "viajar en el tiempo" al futuro, así puedo descubrir cómo se resolverá finalmente un error determinado ;-)

  • Para un archivo dado, vea una lista de las descripciones de las listas de cambios que afectaron el archivo -> también fácil:

    git log filename

    Pero git log es una herramienta mucho más poderosa que solo esto. De hecho, la mayoría de mis scripts personales se conectan con el registro de git para leer el repositorio. Lee la página man.

  • Enviar una lista de cambios pendiente -> También es fácil:

    git commit

Vea mi respuesta a una pregunta anterior para ver mi flujo de trabajo de git típico: Learning Git. Necesito saber si estoy en el camino correcto

Si sigues el flujo de trabajo que describí, entonces encontrarás que herramientas como gitk son mucho más valiosas, ya que te permiten ver claramente grupos de cambios.

Respuesta adicional:

Git es muy flexible y hay varias formas de hacer lo que describes. Lo que hay que recordar es comenzar siempre una nueva rama para cada función en la que estés trabajando. Esto significa que la rama principal no se toca, por lo que siempre puedes volver a ella para corregir los errores. Trabajar en git one casi siempre debería comenzar con:

git checkout -b new-feature-a

Ahora puede editar el archivo a.txt. Para trabajar al mismo tiempo en otra función hazlo:

git checkout master git checkout -b new-feature-z

Ahora puede editar el archivo z.txt. Para volver a a.txt:

git checkout new-feature-a

Pero espere, hay cambios en new-feature-z y git no le permitirá cambiar de ramas. En este punto, tienes dos opciones. El primero es el más simple, confirma todos los cambios en la rama actual:

git add . git commit git checkout new-feature-a

Esto es lo que recomendaría. Pero si realmente no está listo para comprometer el código, puede guardarlo temporalmente:

git stash

Ahora puede cambiar a la rama new-feature-a. Para volver al código en el que estaba trabajando solo haga estallar el alijo:

git checkout new-feature-z git stash pop

Cuando todo está hecho fusiona todos los cambios a master:

git merge --no-ff new-feature-a git merge --no-ff new-feature-z

Debido a que las fusiones son tan rápidas y fáciles (fácil porque los conflictos son tan raros y la resolución de conflictos, cuando sucede uno, no demasiado) usamos branches en git para todo.

Aquí hay otro ejemplo de uso común de ramas en git que no se ve en otras herramientas de control de origen (excepto tal vez mercurial):

¿Necesita seguir cambiando sus archivos de configuración para reflejar su entorno de desarrollo? Luego usa una rama:

git checkout -b dev-config

Ahora edite sus archivos de configuración en su editor favorito y luego confirme los cambios:

git add . git commit

Ahora, cada nueva rama puede comenzar desde la rama dev-config en lugar de master:

git checkout dev-config git checkout -b new-feature-branch

Una vez que haya terminado, elimine las ediciones en dev-config de new-feature-branch utilizando una rebase interactiva:

git rebase -i master

Elimina las confirmaciones que no quieres y luego guarda. Ahora tiene una rama limpia sin ediciones de configuración personalizadas. Es hora de fusionar de nuevo a maestro

git checkout master git merge --no-ff new-feature-branch # because master have changed, it''s a good idea to rebase dev-config: git checkout dev-config git rebase master

Cabe señalar que la eliminación de ediciones con git rebase -i incluso funciona cuando todos los cambios suceden en el mismo archivo. Git recuerda los cambios, no el contenido del archivo *.

* Nota: en realidad, técnicamente no es del todo cierto, pero como usuario es lo que se siente

Más respuesta adicional:

Entonces, a partir de sus comentarios, parece que quiere que existan dos ramas simultáneamente para que pueda probar cómo funciona el código combinado. Bueno, esta es una buena manera de ilustrar el poder y la flexibilidad de las sucursales.

Primero, una palabra sobre la implicación de la ramificación barata y el historial modificable en su flujo de trabajo. Cuando estaba usando CVS y SVN, siempre era un poco reacio a comprometerme. Eso es porque cometer un código inestable inevitablemente f ** k el código de trabajo de otras personas. Pero con git perdí ese miedo. Eso es porque en git otras personas no recibirán mis cambios hasta que los fusione con el maestro. Entonces ahora me encuentro escribiendo código cada 5 líneas que escribo. No necesitas previsión perfecta para comprometerte. Solo necesita cambiar su modo de pensar: commit-to-branch == add-to-changeset, merge-to-master == commit-changeset.

Entonces, volviendo a ejemplos. Así es como lo haría. Supongamos que tiene una rama new-feature-z y desea probarla con new-feature-a . Solo crearía una nueva rama para probarla:

# assume we are currently in branch new-feature-z # branch off this branch for testing git checkout -b feature-z-and-feature-a # now temporarily merge new-feature-a git merge --no-ff new-feature-a

Ahora puedes probar. Si necesita modificar algo para que feature-z funcione con feature-a, hágalo. Si es así, puede fusionar los cambios a la rama correspondiente. Use git rebase -i para eliminar los cambios irrelevantes de la fusión.

Alternativamente, también puede usar git rebase para cambiar temporalmente la base de new-feature-z para apuntar a new-feature-a:

# assume we are currently in branch new-feature-z git rebase new-feature-a

Ahora el historial de ramas se modifica para que new-feature-z se base en new-feature-a en lugar de en master. Ahora puedes probar. Cualquier cambio cometido en esta rama pertenecerá a la rama new-feature-z. Si necesita modificar new-feature-a, simplemente vuelva a cambiar y la rebase para obtener los nuevos cambios:

git checkout new-feature-a # edit code, add, commit etc.. git checkout new-feature-z git rebase new-feature-a # now new-feature-z will contain new changes from new-feature-a

Cuando termines, simplemente vuelve a establecer la base en master para eliminar los cambios de new-feature-a:

# assume we are currently in branch new-feature-z git rebase master

No tengas miedo de comenzar una nueva sucursal. No tengas miedo de comenzar una rama de usar y tirar. No tengas miedo de tirar ramas. Y como merge == submit y commit == add-to-changeset no tengas miedo de cometer a menudo. Recuerde, commit es la herramienta de deshacer definitiva del desarrollador.

Ah, y otra cosa, en las ramas borradas de git todavía existen en su repositorio. Por lo tanto, si accidentalmente borraste algo que luego crees que es útil después de todo, siempre puedes recuperarlo buscando en el historial. Así que no tengas miedo de tirar ramas.


No tengo suficiente experiencia en p4 para producir una hoja de trucos real, pero hay al menos algunas similitudes para recurrir. Un p4 "changeset" es un git "commit".

Los cambios en su espacio de trabajo local se agregan al "índice" con git add , y luego el índice se compromete con la git commit . Entonces, el índice es su lista de cambios pendiente, para todos los efectos.

Observe los cambios con git diff y git status , donde git diff generalmente muestra cambios entre el espacio de trabajo y el índice, pero git diff --cached muestra cambios entre el índice y el repositorio (= su git diff --cached cambios pendiente).

Para obtener información más detallada, recomiendo http://progit.org/book/ . Como conoces el control de versiones en general, probablemente puedas echarle un vistazo y extraer la información específica de git ...


Sufro como usted con la falta del concepto de "lista de cambios" que no es exactamente igual a las ramas de git.

Escribiría un pequeño script que creará un archivo de lista de cambios con la lista de archivos en esa lista de cambios.

Otro comando para enviar solo una determinada lista de cambios simplemente llamando a git commit -a @ change_list_contents.txt y luego a "git commit"

Espero que ayude, Elias