rama - git rebase
¿Cuándo debo usar git pull--rebase? (8)
Conozco a algunas personas que 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?
Creo que deberías usar git pull --rebase
cuando colabores con otros en la misma rama. Usted está en su trabajo → cometer → trabajo → cometer ciclo, y cuando decide impulsar su trabajo, su empuje es rechazado, porque ha habido trabajo paralelo en la misma rama. En este punto siempre hago un pull --rebase
. No uso squash (para aplanar confirmaciones), pero vuelvo a escribir para evitar las confirmaciones de combinación adicionales.
A medida que aumenta su conocimiento de Git, se ve mucho más en el historial que en cualquier otro sistema de control de versiones que haya usado. Si tiene una tonelada de confirmaciones de fusión pequeñas, es fácil perder el foco de la imagen general que está sucediendo en su historia.
Esta es en realidad la única vez que hago rebasado (*), y el resto de mi flujo de trabajo se basa en la fusión. Pero mientras sus comitarios más frecuentes hagan esto, la historia se verá mucho mejor al final.
(*) Mientras enseñaba un curso de Git, hice que un estudiante me arrestara por esto, ya que también abogaba por rebasar las características de las sucursales en ciertas circunstancias. Y él había leído esta respuesta;) Tal rebasamiento también es posible, pero siempre tiene que ser de acuerdo con un sistema preestablecido / acordado, y como tal no debe aplicarse "siempre". Y en ese momento por lo general tampoco hago pull --rebase
, que es de lo que trata la pregunta;)
Creo que se reduce a una preferencia personal.
¿Quieres ocultar tus errores tontos antes de empujar tus cambios? Si es así, git pull --rebase
es perfecto. Le permite aplastar más tarde sus compromisos a unos pocos (o uno). Si tiene fusiones en su historial (no presionado), no es tan fácil hacer una git rebase
adelante.
Personalmente, no me importa publicar todos mis errores tontos, por lo que tiendo a fusionarme en lugar de rebase.
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 sepas, te animamos a ramificar y fusionar. Su sucursal local, en la que tira de los cambios, y la rama remota son, en realidad, diferentes ramas, y git pull
se trata de fusionarlos. Es razonable, ya que presiona no muy a menudo y, por lo general, acumula una serie de cambios antes de que constituyan una característica completa.
Sin embargo, a veces, por el motivo que sea, usted piensa que sería mejor si estos dos, remotos y locales, fueran una sola rama. Como en SVN. Es aquí donde git pull --rebase
entra en juego. Ya no fusionas, realmente te comprometes en la parte superior de la rama remota . De eso se trata en realidad.
Si es peligroso o no es la cuestión de si está tratando una sucursal local y remota como una cosa inseparable. A veces es razonable (cuando sus cambios son pequeños, o si está al comienzo de un desarrollo robusto, cuando los cambios importantes son provocados por pequeños compromisos). A veces no lo es (cuando normalmente crearías otra rama, pero eras demasiado perezoso para hacerlo). Pero esa es una pregunta diferente.
Me gustaría ofrecer una perspectiva diferente sobre lo que realmente significa "git pull --rebase", porque parece que a veces se pierde.
Si alguna vez ha usado Subversion (o CVS), puede estar acostumbrado al comportamiento de "svn update". Si tiene cambios para confirmar y la confirmación falla porque los cambios se han hecho en sentido ascendente, "svn update". Subversion procede mediante la fusión de los cambios anteriores con los suyos, lo que podría generar conflictos.
Lo que Subversion acaba de hacer era esencialmente "pull --rebase". El acto de reformular sus cambios locales para que sean relativos a la versión más reciente es la parte de "rebasar". Si ha realizado "svn diff" antes del intento de confirmación fallido y compara la diferencia resultante con la salida de "svn diff" después, la diferencia entre las dos diferencias es lo que hizo la operación de rebasado.
La principal diferencia entre Git y Subversion en este caso es que en Subversion, "sus" cambios solo existen como cambios no confirmados en su copia de trabajo, mientras que en Git usted tiene confirmaciones reales a nivel local. En otras palabras, en Git has bifurcado la historia; su historia y la historia anterior han divergido, pero usted tiene un antepasado común.
En mi opinión, en el caso normal de tener su sucursal local simplemente reflejando la rama ascendente y haciendo 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 hackeando la historia lineal prevista de una rama. El hecho de que alguien más haya presionado un poco antes de su intento de empuje es irrelevante, y parece contraproducente que cada accidente de tiempo de ese tipo resulte en fusiones en la historia.
Si realmente siente la necesidad de que algo sea una sucursal por cualquier razón, esa es una preocupación diferente en mi opinión. Pero a menos que tenga un deseo específico y activo de representar sus cambios en forma de fusión, el comportamiento predeterminado debería, en mi opinión, ser "git pull --rebase".
Considere a otras personas que necesitan observar y entender la historia de su proyecto. ¿Desea que la historia esté repleta de cientos de fusiones en todo el lugar, o solo desea algunas fusiones selectas que representan fusiones reales de esfuerzos de desarrollo divergentes intencionales?
No creo que haya una razón para no usar pull --rebase
- pull --rebase
código a Git específicamente para permitir que mi comando git pull
siempre rebase contra las confirmaciones en sentido ascendente.
Al mirar a través del historial, nunca es interesante saber cuándo se detuvo la sincronización del hombre / chica que estaba trabajando en la función. Puede ser útil para el chico / chica mientras lo está haciendo, pero para eso está el reflog
. Solo está agregando ruido para todos los demás.
Quizás la mejor manera de explicarlo es con un ejemplo:
- Alice crea la rama A del tema y trabaja en ella.
- Bob crea una rama de tema no relacionada B, y trabaja en ella
- Alice hace
git checkout master && git pull
. El maestro ya está actualizado. - Bob hace
git checkout master && git pull
. El maestro ya está actualizado. - Alice hace
git merge topic-branch-A
- Bob hace
git merge topic-branch-B
- Bob hace
git push origin master
antes de Alice - Alice hace
git push origin master
, que se rechaza porque no es una combinación de avance rápido. - Alice mira el registro de origen / maestro, y ve que el compromiso no está relacionado con el suyo.
- Alice hace
git pull --rebase origin master
- El compromiso de fusión de Alice se desenrolla, el compromiso de Bob se tira y el compromiso de Alice se aplica después del compromiso de Bob.
- Alice hace
git push origin master
, y todos están contentos de no tener que leer una confirmación de fusión inútil cuando miran los registros en el futuro.
Tenga en cuenta que la rama específica en la que se fusiona es irrelevante para el ejemplo. Maestro 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 combinando simultáneamente sus sucursales locales en una sucursal remota compartida.
Solo recuerda:
- pull = fetch + fusionar
- pull --rebase = fetch + rebase
Por lo tanto, elige la forma en que quieres manejar tu rama.
Será mejor que sepas la diferencia entre fusionar y rebase :)
git pull --rebase
puede ocultar una reescritura del historial de un colaborador git push --force
. Recomiendo usar git pull --rebase
solo si sabe que olvidó enviar sus confirmaciones antes de que otra persona haga lo mismo.
Si no ha cometido nada, pero su espacio de trabajo no está limpio, solo git stash
antes de git pull
. De esta manera, no volverá a escribir su historial en silencio (lo que podría eliminar parte de su trabajo en silencio).