Trabajando en equipo con git

Aprender a usar los comandos básicos de git para nuestro día a día es muy sencillo, pero no todo el mundo tiene claro como trabajar correctamente en equipo.

Para trabajar en equipo no es tan importante un conocimiento más profundo de git como seguir buenas practicas.

Una rama por funcionalidad

Crea una rama (branch) a partir de master por cada funcionalidad que desarrolles.

Esto te permite a ti y a los demás revisar los cambios antes de mergear a master manualmente o con los pull requests de Github u otros servicios.

Para la revisión siempre es de agradecer, quizás exigible pull requests cortos y concisos en la medida de lo posible. Los commits deben de explicar que hacen y debemos de mantener el histórico de commits limpio. Es decir, evitar mensajes duplicados, commits que arreglan commits anteriores, etc.

Mantener el log limpio

Para mantener el log limpio a pesar de que nos equivoquemos, deshagamos cosas, hagamos commit para compartir nuestros avances o la razón que sea siempre podemos usar el rebase.

Por ejemplo, imagina que tenemos:

git init .

$ touch foo.rb
$ git add foo.rb
$ git commit -m "Add foo"

git commit -b new-feature

$ touch baz.rb
$ git add baz.rb
$ git commit -m "Add baz"

$ git log --oneline
# output: 
#   57ad776 Add baz
#   a2fe030 Add foo

Y descubrimos que nuestro ùltimo commit está mal... Queremos renombrar el fichero y cambiar el mensaje. Para eso tenemos git commit --ammend:

$ mv baz.rb bar.rb
$ git add bar.rb
$ git commit --ammend -m "Add bar"

$ git log --oneline
# output: 
#   7c72bb2 Add bar
#   a2fe030 Add foo

Esta es la forma más rápida. Podemos hacer ediciones más complicadas gracias a git rebase -i master. Normalmente será master pero puede ser otra rama, commit o tag.

Al ejecutar este comando te mostrará el editor de texto que tengas configurado con los commits y documentación sobre lo que puedes hacer.

# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

En mi día a día solo uso 3 acciones a parte de pick.

Una vez estemos contento con el histórico podemos hacer git push.

Si hicimos push previamente nos dará un error parecido a este:

To https://git.example.com/tutoronrails.git
 ! [rejected]        new-feature -> new-feature (non-fast-forward)
error: failed to push some refs to 'https://git.example.com/tutoronrails.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Esto nos recuerda un punto importante...

Nos reescriba el histórico de ramas compartidas

Nos reescriba el histórico de ramas compartidas a menos que estés de acuerdo con tus compañeros.

Si estás trabajando con alguien más en una rama es mejor no reescribir el historico. Por eso es mejor no trabajar nunca sobre master.

Con git push --force forzarás el repositorio remoto con tus cambios haciendo que quizas tus compañeros tengan conflictos.

Una opción más civilizada es usar git push --force-with-lease, comprueba que tu copia local contiene los últimos cambias de la copia remota que estás a punto de sobreescribir. Es decir, que nadie a subido algo nuevo y vas a borrarlo.

Pero lo mejor es dejar esto para el final cuando no queremos añadir más código a nuestra rama.

Alguien hizo git push -f

Si alguien sobrescribe el historico de una rama compartida puedes hacer varias cosas, entre ellas:

Sobreescribir tu copia local con lo que hay en el servidor origin:

$ git reset --hard origin/new-feature

O hacer git pull --no-ff y git rebase -i master para resolver los conflictos.

También le puedes compartir este artículo.


Comentarios