git ready

aprendiendo git de a un commit por vez
por Nick Quaranto, traducido por Matías Flores

buscando commits ya integrados

publicado el 03 Apr 2009

¿Alguna vez has visto este mensaje al intentar eliminar una rama?

$ git branch -d docs
error: The branch 'docs' is not an ancestor of your current HEAD.
If you are sure you want to delete it, run 'git branch -D docs'

Esto ocurre porque la rama que deseas eliminar no está incluída en la rama actual. Este es uno de esos casos en los que Git está intentando evitar que pierdas datos de forma accidental. Entonces, ¿cómo podemos determinar si una rama determinada (o un commit) forma parte de la rama actual, sin intentar eliminar dicha rama?

El comando git branch provee algunas opciones que nos pueden ser de utilidad. La opción --contains, por ejemplo, nos permite determinar si un commit específico fue integrado ya en la rama actual. Tal vez tienes el SHA de un commit que crees que ya aplicaste en la rama actual pero no estás seguro, o quieres chequear si aquél commit de tu proyecto open source favorito que reduce el uso de memoria en un 75% está incluído en la rama actual o no.

$ git log -1 tests
commit d590f2ac0635ec0053c4a7377bd929943d475297
Author: Nick Quaranto <nick@quaran.to>
Date:   Wed Apr 1 20:38:59 2009 -0400

    Green all around, finally.

$ git branch --contains d590f2
  tests
* master

De acuerdo con los resultados obtenidos, podemos determinar que el commit d590f2 ha sido aplicado en las ramas tests y master.

Pero volvamos a nuestro problema original: ¿cómo determinar si una rama completa fue aplicada o no? Las opciones --merged y --no-merged hacen precisamente esto por nosotros. La primera nos dirá cuáles son las ramas que tienen aplicado el treeish especificado, mientras que la segunda opción hará exactamente lo contrario.

En este caso, la rama docs no fue completamente aplicada en master:

$ git branch --merged docs
  docs

$ git branch --no-merged docs
  config
* master
  tests

$ git branch -d docs
error: The branch 'docs' is not an ancestor of your current HEAD.
If you are sure you want to delete it, run 'git branch -D docs'.

$ git branch -D docs
Deleted branch docs (884583c).

Si eres valiente, puedes usar una combinación de git rev-parse y git rev-list para determinar si un commit en particular está incluído en la historia de una rama o no. Originalmente yo lo hacía de ese modo hasta que alguien en el #git IRC channel me comentó la solución obvia utilizando git branch. rev-parse toma un treeish y lo convierte en el SHA al que pertenece. rev-list permite listar commits de distintas maneras, suficientes como para merecer su propio artículo.

$ git rev-list master | grep $(git rev-parse docs)
$ git rev-list master | grep $(git rev-parse tests)
d590f2ac0635ec0053c4a7377bd929943d475297

El primer comando no devolvió nada, ya que el commit apuntado por HEAD en docs no existe en master aún. Por otro lado, el commit apuntado por HEAD en tests es encontrado en master y listado, tal como se esperaba.

Espero que este artículo te ahorre algo de tiempo cuando estés trabajando con múltiples ramas y necesites saber si ya fueron integradas o no. Si tienes alguna otra sugerencia acerca de cómo manejar esta situación, ¡dejanos un comentario!