¿Cuándo debo usar git pull --rebase?
Conozco algunas personas que lo usan git pull --rebase
por defecto y otras que insisten en no usarlo nunca. Creo que entiendo la diferencia entre fusionar y rebasar, pero estoy tratando de poner esto en el contexto de git pull
. ¿Se trata simplemente de no querer ver muchos mensajes de confirmación de fusión o hay otros problemas?
Me gustaría ofrecer una perspectiva diferente sobre lo que git pull --rebase
realmente significa, porque a veces parece perderse.
Si alguna vez ha utilizado Subversion (o CVS), es posible que esté acostumbrado al comportamiento de svn update
. Si tiene cambios que confirmar y la confirmación falla porque los cambios se realizaron en sentido ascendente, usted svn update
. Subversion procede fusionando los cambios anteriores con los suyos, lo que puede generar conflictos.
Lo que Subversion acaba de hacer fue esencialmente git pull --rebase
... El acto de reformular los cambios locales para que sean relativos a la versión más nueva es la parte de "rebase". Si lo había hecho svn diff
antes del intento fallido de confirmación y compara la diferencia resultante con la salida svn diff
posterior, la diferencia entre las dos diferencias es lo que hizo la operación de cambio de base.
La principal diferencia entre Git y Subversion en este caso es que en Subversion, "tus" cambios sólo existen como cambios no confirmados en tu copia de trabajo, mientras que en Git tienes confirmaciones reales localmente. En otras palabras, en Git has bifurcado el historial; vuestra historia y la historia anterior han divergido, pero tenéis un ancestro común.
En mi opinión, en el caso normal de que su sucursal local simplemente refleje la sucursal ascendente y realice un desarrollo continuo en ella, lo correcto es siempre --rebase
, porque eso es lo que realmente está haciendo semánticamente . Usted y otros están destrozando la historia lineal prevista de una rama. El hecho de que alguien más haya empujado un poco antes de su intento de empujar es irrelevante, y parece contraproducente que cada accidente de sincronización resulte en fusiones en el historial.
Si realmente siente la necesidad de que algo sea una sucursal por cualquier motivo, en mi opinión, esa es una preocupación diferente. Pero a menos que tenga un deseo específico y activo de representar sus cambios en forma de combinación, el comportamiento predeterminado debería, en mi opinión, ser git pull --rebase
.
Considere a otras personas que necesitan observar y comprender la historia de su proyecto. ¿Quiere que la historia esté plagada de cientos de fusiones por todas partes, o quiere sólo las pocas fusiones seleccionadas que representan fusiones reales de esfuerzos de desarrollo intencionales divergentes?
Debes usar git pull --rebase
cuando
- tus cambios no merecen una rama separada
De hecho, ¿por qué no entonces? Es más claro y no impone una agrupación lógica en sus confirmaciones.
Ok, supongo que necesita alguna aclaración. En Git, como probablemente sepa, se le recomienda realizar bifurcaciones y fusiones. Su sucursal local, en la que realiza cambios, y su sucursal remota son, en realidad, sucursales diferentes y git pull
se trata de fusionarlas. Es razonable, ya que no presiona con mucha frecuencia y generalmente acumula una cantidad de cambios antes de que constituyan una característica completa.
Sin embargo, a veces, por cualquier motivo, piensas que en realidad sería mejor si estas dos, remota y local, fueran una sola sucursal. Como en SVN. Es aquí donde git pull --rebase
entra en juego. Ya no se fusiona; en realidad, se compromete sobre la rama remota . De eso se trata realmente.
Si es peligroso o no, es la cuestión de si está tratando a las sucursales locales y remotas como una cosa inseparable. A veces es razonable (cuando los cambios son pequeños, o si se encuentra al comienzo de un desarrollo sólido, cuando se realizan cambios importantes mediante pequeñas confirmaciones). A veces no lo es (cuando normalmente crearías otra rama, pero eras demasiado vago para hacerlo). Pero esa es una pregunta diferente.
Quizás la mejor forma de explicarlo sea con un ejemplo:
- Alice crea la rama temática A y trabaja en ella.
- Bob crea la rama B del tema no relacionado y trabaja en ella.
- Alicia lo hace
git checkout master && git pull
. El máster ya está actualizado. - Bob lo hace
git checkout master && git pull
. El máster ya está actualizado. - Alicia lo hace
git merge topic-branch-A
- bob lo hace
git merge topic-branch-B
- Bob lo hace
git push origin master
antes que Alice. - Alice lo hace
git push origin master
, lo cual se rechaza porque no es una fusión de avance rápido. - Alice mira el registro de origen/maestro y ve que la confirmación no está relacionada con la de ella.
- Alicia lo hace
git pull --rebase origin master
- La confirmación de fusión de Alice se desenrolla, la confirmación de Bob se retira y la confirmación de Alice se aplica después de la confirmación de Bob.
- Alice lo hace
git push origin master
, y todos están felices de no tener que leer una confirmación de fusión inútil cuando vean los registros en el futuro.
Tenga en cuenta que la rama específica en la que se fusionará es irrelevante para el ejemplo. Master en este ejemplo podría ser fácilmente una rama de lanzamiento o una rama de desarrollo. El punto clave es que Alice y Bob están fusionando simultáneamente sus sucursales locales en una sucursal remota compartida.