Capital Software Blog

Git Workflows: trabajo en solitario frente a trabajo en equipo… y más

En este artículo, facilitamos flujos de trabajo para casi todo lo que necesitarás hacer con Git:

  • Comandos básicos de Git
  • Configurar un repositorio remoto y empujar a Github
  • Deshacer cosas en Git
  • Ignorando cosas en Git
  • Ramas de Git para nuevas características
  • Trabajar solo vs en equipo
  • Bifurcación y contribución al código abierto

Comandos básicos de Git

Estos son los comandos que usará en cada proyecto.

  1. Inicializar Git

git init <project-name>

  1. Agregar archivos al área de ensayo

Para agregar todos los archivos:

git add.

Para agregar todos los archivos en una carpeta específica:

git add src/posts/Git_Commands_Post

Para agregar un archivo:

git add styles.css

Para agregar todos los archivos con una extensión específica (en este caso, todos los archivos html):

git add *.html

Para agregar partes de un archivo:

git add -p (y=sí, n=no, s=dividir en partes más pequeñas, e=editar parte manualmente, q=salir)

  1. Verifique que el área de preparación sea correcta antes de comprometerse con Git

git status

  1. Confirmar los cambios en Git

git commit -m "A short message describing the changes here"

Para agregar todos los cambios a los archivos rastreados y confirmarlos en una línea:

git commit -am "commit message"

Para agregar cambios por etapas a la confirmación anterior (tiene la opción de cambiar el nombre de la confirmación):

git commit --amend

  1. Empujar al repositorio remoto (consulte a continuación cómo configurar el repositorio remoto)

git push

Configurar un repositorio remoto y empujar a Github

Primero necesitamos configurar el repositorio en Github:

  1. Ir a github.com
  2. Inicia sesión o crea una cuenta
  3. Seleccione «Nuevo» para crear un nuevo repositorio
  4. Escriba la información de su repositorio. Siempre dejo las casillas «Agregar un archivo README», «Agregar un .gitignore» y «Elegir una licencia» sin marcar.
  5. Haga clic en «Crear repositorio»

Ahora necesitamos conectar nuestro repositorio local al repositorio Github recién creado:

  1. Agregue el repositorio remoto.

git remote add origin https://github.com/YourUsername/Your-remote-repo-name.git

  1. Asegúrese de que estamos en la sucursal principal

git branch -M main

  1. Empuje su código local comprometido a Github

git push -u origin main

Sincronización con repositorios remotos

git remoto

Los registros registrados a través del git remotecomando se pueden usar junto con los comandos git fetch, git push y git pull. El comando remoto git es realmente una forma más fácil de pasar URL a estos comandos de «compartir».

git remote add <name> <url>

<name> se puede usar como acceso directo en los otros comandos para compartir.

Nota: Cuando clona un repositorio con git clone, crea automáticamente una conexión remota llamada origen que apunta al repositorio clonado.

Para ver todas las conexiones a repositorios remotos:

git remote

Para ver las URL:

git remote -v

Eliminar la conexión a un repositorio:

git remote rm <name>

Cambiar el nombre de una conexión remota:

git remote rename <old-name> <new-name>

Buscar

Puede obtener confirmaciones, archivos y referencias de un repositorio remoto en su repositorio local con git fetch. Es más seguro que git pullporque no fusiona automáticamente el contenido en el estado de trabajo de su repositorio local.

Obtenga todas las ramas del repositorio remoto ( <remote>es lo que llamó la conexión con git remote):

git fetch <remote>

Obtener rama especificada (por ejemplo, función de compañeros de trabajo):

git fetch <remote> <branch>

Una vez que tenemos el contenido que queremos, debemos integrarlo en nuestra copia local.

Si desea sincronizar su repositorio local con la rama principal del repositorio central:

  1. git fetch origin
  2. Vea qué compromisos se han agregado:

git log --oneline main..origin/main

  1. git checkout main
  2. git merge origin/main

Si buscó una sucursal remota y desea continuar trabajando en ella:

  1. Enumere todas las sucursales remotas:

git branch -r

  1. Consulta la sucursal que queremos integrar

git checkout origin/coworkers-feature

  1. Cree una nueva sucursal local y finalice la compra.

git checkout -b local_feature_branch

Ahora podemos seguir trabajando en la función desde nuestra copia local.

Git Pull

Una combinación de dos cosas: git fetchseguido de git merge. No es tan seguro como git fetchaltera su copia local.

git pull <remote>

Esto obtiene la copia remota especificada de la rama actual y luego la fusiona con la copia local.

es equivalente a:

git fetch <remoto>git merge origen/<rama-actual>

Sin compromiso:

git pull --no-commit <remote>

Es muy común sincronizar con la rama principal del repositorio remoto central usando un rebase.

git checkout main

git pull --rebase origin

Esto simplemente mueve sus cambios locales a la parte superior de lo que ha contribuido su equipo. Mantiene un buen historial lineal al evitar confirmaciones de combinación innecesarias. Pero cambiar la base reescribe la historia: los principiantes están más seguros usando la combinación.

Git Push

Se utiliza para cargar contenido local en un repositorio remoto.

git push <remote> <branch>

Esto crea una sucursal local en el repositorio de destino. Para evitar que sobrescriba las confirmaciones, git no le permitirá presionar cuando resulte en una combinación que no sea de avance rápido en el repositorio de destino. Las fusiones que no son de avance rápido son el resultado de una historia remota que diverge de su historia local. Puede extraer la rama remota y fusionarla con la local antes de presionar.

Para forzar el empuje, incluso si da como resultado una combinación que no sea de avance rápido (elimine cualquier cambio anterior que haya ocurrido desde su último tirón):

git push <remote> --force

Empuje todas las sucursales locales:

git push <remote> --all

Eliminar una sucursal local:

git branch -D <branch-name>

Eliminar una sucursal remota:

git push origin :<branch-name>

Cambiar su nombre de usuario y correo electrónico en Git

git config --usuario global.nombre "Danny Adams"
git config --usuario global.email "[email protected]"

Deshacer cosas en Git

Eliminar un archivo de la puesta en escena

El siguiente comando elimina el archivo solo del repositorio de Git. La copia del directorio de trabajo local del archivo permanecerá intacta; esto se garantiza agregando la --cachedopción.

git rm --cached <filename>

Para eliminar todos los archivos en una carpeta, agregue la bandera recursiva:

git rm --cached <filename> -r

Volver a una confirmación anterior de SOLO LECTURA

Para ver cómo se veían las cosas en una confirmación en particular, sin volver a escribir el historial o eliminar cosas, simplemente podemos:

  1. Registre el historial de confirmaciones y copie la ID de la confirmación a la que queremos volver

git log --oneline

  1. Retroceder en el tiempo hasta el compromiso.

git checkout <commit_ID>

  1. Una vez hecho esto, volver a donde estábamos

git checkout main

Revertir una confirmación

Revertir confirmación crea una nueva confirmación, donde se deshacen los cambios realizados en una confirmación específica.

Digamos que queríamos deshacer lo que hicimos en la confirmación 2 de la siguiente rama:

Rama de 3 compromisos

Al usar Revert, se realizaría una nueva confirmación, donde los cambios realizados en C2 se deshacen, pero C2 aún se mantiene en el historial, por lo que aún podríamos regresar y conservar los cambios si decidimos que los queremos nuevamente:

Rama de 3 compromisos

Veamos un ejemplo. A continuación, tengo 3 compromisos en mi proyecto, con el último en la parte superior:

registro de confirmación de git

Digamos que quería deshacer los cambios que hice con la confirmación «Created styles.css» solamente. Simplemente puedo revertir este compromiso:

git revert a432c9f

Luego, Git abrirá un archivo en su editor de texto (si está usando código VS) y le pedirá que cree un mensaje para la nueva confirmación:

Git revertir cmd

Git revertir mensaje

De forma predeterminada, el mensaje de confirmación dice ‘Revertir «Estilos creados.css»‘, pero esto se puede cambiar a lo que quieras. Normalmente lo dejo como está.

Una vez que esté satisfecho con el mensaje, simplemente cierre el archivo y Git agregará la nueva confirmación donde se deshacen los cambios de «Crear estilos.css».

Pero aquí está la belleza de usar revertir para deshacer cosas: el historial de confirmaciones todavía está allí.

registro de git después de revertir

Como puede ver, el compromiso «Estilos creados.css» todavía está allí. Revertir simplemente ha realizado una nueva confirmación donde los cambios realizados en «Estilos creados.css» se revierten (deshacer). Esto es MUCHO más seguro que usar Restablecer, la siguiente sección, que elimina las confirmaciones.

Restablecer compromiso

Restablecer compromiso retrocede en el tiempo a un compromiso anterior y elimina permanentemente todos los compromisos que ocurrieron antes de él.

Restablecer rama de confirmaciones

  1. Obtenga la identificación de la confirmación a la que desea volver

git log --oneline

  1. Reiniciar

git reset <commit_ID>

Nota: todos los cambios de código seguirán estando en los archivos del espacio de trabajo, pero no se confirmarán. Para eliminar de Git Y tu espacio de trabajo, usa:

git reset <commit_ID> --hard (Muy peligroso, ¡ten mucho cuidado!)

Dile a Git que ignore ciertos archivos

Algunos archivos de su proyecto contendrán información privada, como contraseñas y claves. Es muy importante que esta información no se envíe a Github. Además, las carpetas como node_modules y los directorios de salida de compilación pueden ocupar mucho espacio en el disco, y no es necesario enviarlos a Github, ya que se pueden reinstalar o compilar en cualquier momento.

  1. Crea un .gitignorearchivo en la raíz de tu proyecto.
  2. Agregue los nombres de las carpetas y los archivos que desea ignorar:
node_modulescontraseña-secreta.txt

Es importante agregar estos archivos a .gitignore tan pronto como se creen. Pero si los ha enviado accidentalmente a git, puede deshacer el seguimiento de cada uno con los siguientes comandos:

  1. Agregue el archivo a .gitignore
  2. git rm --cached <filename>
  3. git commit -m "Start ignoring <filename>"

O si tiene muchos archivos que necesita eliminar:

  1. Agregar archivos a .gitignore
  2. Eliminar todo del repositorio

git rm -r --cached .

  1. Vuelva a agregar todo

git add .

Ahora todo, excepto los archivos en su .gitignore, se agregará al área de preparación.

  1. Cometer

git commit -m ".gitignore fix"

El repositorio local ahora está limpio. Envíe los cambios a Github para ver los cambios efectivos allí también.

Fusionar una rama de funciones en la principal

Un paradigma común de Git es mantener siempre la rama principal implementable. Esto significa que cada vez que esté trabajando en una nueva función, debe crear una nueva rama y comprometerse con ella. Luego, una vez que la función esté completa, puede fusionarla nuevamente en main.

Fusionar una característica

Cuando trabaja solo

Si es el único que contribuye a un repositorio, puede fusionar de manera segura una función en la principal sin crear una solicitud de extracción.

  1. Crea una nueva rama y entra en ella.

git checkout -b <branch-name>

  1. Realiza tus cambios en esta sucursal. Agregue y confirme sus cambios tantas veces como sea necesario.
  2. Pagar a principal y fusionar la rama de funciones en principal

git checkout main

git merge <branch-name> --no-ff

El indicador de no avance rápido crea una nueva confirmación de combinación y mantiene el historial de las ramas de funciones. Sin esta bandera, el encabezado simplemente avanzará rápidamente hasta el final de la función sin una nueva confirmación de fusión.

Git fastforward vs no-fastforward

Cuando se trabaja en equipo

Digamos que alguien te ha agregado a un repositorio de Github, para que ahora puedas contribuir como parte del equipo.

Para contribuir, deberá realizar una solicitud de extracción. Una solicitud de extracción es para comunicar y revisar el código, antes de fusionarlo con main. La fusión directa y la fusión con una solicitud de extracción son idénticas; la única diferencia es que una solicitud de extracción crea un foro dedicado en Github para la discusión, lo que permite a los miembros del equipo revisar su código antes de fusionarlo.

  1. Clonar el repositorio de Github

git clone <repo-url>

  1. Asegúrese de que nuestro código esté actualizado

Antes de realizar cualquier cambio, siempre debe asegurarse de que su copia local esté actualizada con el repositorio remoto, ya que otros desarrolladores pueden haber contribuido. Obtenga el código más reciente del repositorio remoto.

git pull origin main

  1. Crear y finalizar la compra en una nueva sucursal

git checkout -b <branch-name>

  1. Haz los cambios deseados
  2. Agregar y confirmar cambios

git add .

git commit -m "some message"

  1. Empuje el código en esta rama a una rama en Github

git push origin <name-of-branch-for-Github>

  1. Crear una solicitud de extracción

Vaya a la rama principal del repositorio de Github y haga clic en «comparar y extraer solicitud».

  1. Deje un comentario para explicar exactamente lo que ha hecho, luego «cree una solicitud de extracción».

Otros miembros del equipo recibirán un correo electrónico con la solicitud de extraer su código a main. Pueden ver cambios, ver confirmaciones, dejar comentarios y (si están contentos) fusionar el código en main.

La rama de función se puede eliminar una vez fusionada.

Pero, ¿qué sucede si las personas realizan cambios en main mientras aún está trabajando en la rama de características?

  1. Confirme o guarde los cambios realizados en la rama de características.
  2. git checkout main
  3. git pull origin main
  4. git checkout <feature-branch-name>
  5. Combinar la rama principal más reciente en su rama de características

git merge main

Ahora puede incorporar los últimos cambios de otros desarrolladores en su función.

Nota: es posible que deba solucionar los conflictos de fusión. Esto es normal y forma parte de trabajar con Git.

Forking y contribución a proyectos de código abierto

Si no tiene acceso de escritura a un repositorio, pero aún desea contribuir, puede bifurcar el proyecto:

  1. Encuentre un repositorio público de código abierto
  2. Fork the repo (cree una copia en su propia cuenta de Github)
  3. git clone <url-of-your-fork>
  4. Realice cambios (también podría crear una nueva rama para los cambios y luego enviarlos a una nueva rama)
  5. git add . git commit -m "message" git push origin main
  6. Vaya a su copia bifurcada en Github y haga clic en «Nueva solicitud de extracción»
  7. «Crear solicitud de extracción»: esto extrae su código en el repositorio principal para revisarlo y fusionarlo. NO PUEDES FUSIONAR ESTO: solo se permiten los propietarios del repositorio.

Squash

Una rama de función puede tener muchas confirmaciones. Es posible que no desee que todas estas confirmaciones se muestren en la rama principal después de la fusión. Puedes agrupar todas las confirmaciones en una sola:

git git merge --squash <feature-branch>

Esto combinará todos los cambios de la rama de funciones, pero no los confirmará (a diferencia de una combinación normal que crea una confirmación de combinación automática). A continuación, puede agregar y confirmar los cambios. Aparecerá como si el trabajo de su función hubiera ocurrido en una sola confirmación.

«Squash and merge» y «Rebase and merge» también son opciones en Github para cerrar una solicitud de extracción.

Nota: si desea limpiar una rama sin fusionarla, use el cambio de base interactivo (consulte a continuación).

Incorporación de cambios ascendentes en una rama de características

Supongamos que ha creado una nueva rama de características y ha realizado algunas confirmaciones. Mientras trabajaban, sus compañeros de trabajo enviaron cambios a la rama principal en el repositorio remoto. Se parece a esto:

Ramas principales y características iniciales

Puede incorporar los últimos cambios realizados por sus compañeros de trabajo en su función de una de dos maneras: fusionando o reorganizando. (Incluso si los cambios no tienen nada que ver con su característica, incorporar los cambios más recientes en la rama de características en este punto puede hacer que sea más fácil fusionar la función en principal cuando haya terminado; puede evitar una gran acumulación de conflictos de fusión).

Pero primero, necesitamos obtener los últimos cambios.

  1. Confirme o guarde los cambios realizados en la rama de características.
  2. git checkout main
  3. git pull origin main

Ahora podemos fusionar o reorganizar para incorporar estos nuevos cambios en nuestra rama de funciones…

Fusión

Así es como se verían las cosas si fusionaras main con tu rama de características:

git checkout feature
git merge main

La ventaja de la fusión es que no es destructiva. Las ramas existentes no se modifican de ninguna manera (a diferencia del cambio de base).

El problema con esto es que si la rama principal se actualiza con frecuencia, enturbiará el historial de confirmaciones de su característica. Si esto es una preocupación, la rebase podría ser una buena opción.

Rebase

Así es como se verían las cosas después del rebase:

git checkout feature
git rebase main
Después de fusionar

Toda la rama de funciones se ha movido para comenzar en la punta de la rama principal, incorporando efectivamente todos los nuevos cambios en main. Pero, en lugar de usar una confirmación de fusión, la reorganización vuelve a escribir el historial del proyecto mediante la creación de nuevas confirmaciones para cada confirmación en la rama original.

El rebase da como resultado un historial de proyecto mucho más limpio, ya que no hay confirmaciones de fusión cada vez que queremos incluir nuevos cambios en main.

Pero, el rebase puede ser peligroso ya que reescribe la historia del proyecto. Siga siempre la regla de oro: NUNCA REBASE EN SUCURSALES PÚBLICAS. Main, por ejemplo, es una rama pública ya que otros miembros del equipo tienen acceso a ella y pueden construir a partir de ella. Cambiar su historia podría llevar a una confusión masiva. Su rama de función, local en su PC, se puede cambiar de base, pero una vez que la envía para una solicitud de extracción, es una rama pública, así que no cambie de base.

Limpieza local – Rebase interactivo

Si desea limpiar las confirmaciones de la rama de características antes de volver a la base principal, puede usar la reorganización interactiva:

función de pago de gitgit regit checkout feature
git rebase -i main

Git luego abrirá un archivo en su editor de texto:

Archivo de editor de texto de rebase interactivo

En este archivo, podemos modificar el historial de confirmaciones de nuestra rama de funciones antes de volver a establecer la base principal. Por ejemplo, si la segunda confirmación soluciona un pequeño problema en la primera confirmación, puede condensarlos en una sola confirmación con el comando de corrección:

Archivo de editor de texto de rebase interactivo

Cuando cerremos el archivo, git realizará el rebase como lo solicitamos.

La eliminación de confirmaciones insignificantes hace que el historial de la función sea más fácil de entender. Esto es algo que la fusión no puede hacer.

Si no necesita incorporar cambios ascendentes, o no necesita cambiar el historial de toda la rama de funciones, puede especificar cuántas confirmaciones desea reorganizar:

git checkout feature
git rebase -i HEAD~3

Esto le permite volver a escribir de forma interactiva las últimas 3 confirmaciones.

Stash

Stashing almacena temporalmente los cambios que ha realizado en su copia de trabajo para que pueda cambiar de forma segura a otra rama y trabajar en otra cosa, luego regrese y vuelva a aplicar los cambios más adelante. Es útil si aún no está listo para confirmar su cambio de código.

git stash

Esto ocultó los cambios preparados y no preparados, pero no los archivos locales nuevos que aún no se han preparado ni los archivos ignorados por git.

Es una buena práctica describir sus alijos al guardar:

git stash save "half of nav hamburger is complete"

git stash -u(o --include-untrackedincluye archivos sin seguimiento)

git stash -a(o --allincluye archivos ignorados y sin seguimiento)

Para volver a aplicar el alijo sin eliminarlo (útil si desea aplicarlo a varias sucursales):

git stash apply

O podemos sacar el alijo de la pila:

git stash pop

Múltiples stashing

Enumere todos los escondites:

git stash list

Elija qué alijo volver a aplicar:

git stash pop [email protected]{2}

Visualización de stash diffs

Para ver la diferencia del último alijo que hiciste:

git stash show

Muestra la diferencia de un alijo en particular:

git stash show [email protected]{1}

Resultado de mostrar alijo

Para ver la diferencia completa de un alijo, pase --path-p:

git stash show -p

Resultado del parche Stash Show

Stashing parciales

Para guardar un solo archivo, una colección de archivos o cambios individuales desde dentro de los archivos:

git stash -p

Esto iterará a través de cada «trozo» modificado en su copia de trabajo y le preguntará si desea guardarlo.

Línea de comando de parche oculto

Creando una rama desde tu stash

Echa un vistazo a una nueva rama y coloca tus cambios ocultos en ella:

git stash branch <branch-name> [email protected]{2}

Esto es útil si los cambios en su rama divergen de los cambios en su alijo; puede generar conflictos al abrir o aplicar su alijo.

Eliminación de stash

git stash drop [email protected]{1}

Para borrar todo:

git stash clear

Diffing

La función de diferenciación toma dos conjuntos de datos de entrada y genera las diferencias entre ellos. Estas fuentes de datos pueden ser compromisos, ramas, archivos y más.

git diff

VS Code facilita la visualización de las diferencias entre los archivos en la pestaña Control de código fuente .