¿Cuál es la diferencia entre `git fetch` y luego` git rebase`, y `git pull –rebase`?

Al leer la página de git pull , da esta severa advertencia sobre git pull --rebase :

Este es un modo de operación potencialmente peligroso. Reescribe la historia, lo que no augura nada cuando ya publicaste ese historial. No use esta opción a less que haya leído git-rebase (1) cuidadosamente.

En la página de git rebase , da mucha descripción, pero no hay advertencia de este tipo.

Además, he visto a algunas personas decir que

 git fetch git rebase 

es lo mismo que

 git pull --rebase 

mientras que otros dicen que son ligeramente diferentes.

¿Cuál es la verdad?

La regla con git es que nunca debe intentar cambiar el historial después de haber sido compartido / publicado / presionado. Puede hacerlo, por supuesto, si realmente quiere y tiene suficientes permissions, pero debe hacerse con mucho cuidado, ya que puede molestar a otras personas.

Ahora, afortunadamente, cuando tienes un deployment de git típico con un único repository de origen (origen) que es la fuente de todo lo que es bueno y verdadero en el universo, puedes usar git pull --rebase al git pull --rebase de tu corazón y será perfectamente seguro y en mi opinión, darle una historia mucho más sensata (es decir, lineal). Yo y mi equipo lo usamos continuamente.

Sin embargo, si comienzas a tener múltiples controles remotos y comienzas a hacer git pull --rebase <arguments> para que ya no vuelvas a basar contra el mismo objective cada vez, o comiences a empujar tu twig a repositorys alternativos antes de ejecutar git pull --rebase con tu primaria aguas arriba, entonces puede comenzar a tener problemas. En cualquier momento en que comparta sus cambios con otro remoto / repository y luego cambie esos cambios (para valores de cambio equivalentes a cambiar el SHA / padre / etc. incluso si el post / contenido de confirmación no cambió), puede ensuciar a la persona que tenía los viejos cambios.

Siempre y cuando no te salgas del sobre de la cordura de rebase, git pull --rebase será muy bueno para ti.

Eso, err, no responde a la pregunta sobre la diferencia entre git pull --rebase y git fetch && git rebase @{u} Voy a seguir adelante y decir que no estoy al tanto de ninguna diferencia y si hay una, es lo suficientemente sutil como para no haberlo notado en los años que he usado git. Posiblemente porque el sistema averigua el repository correcto que debe search su sucursal si tiene múltiples repositorys y el "origen" no es el ascendente de esta twig.

Y aunque te vayas muy mal con git-rebase, puedes recuperarte de nuevo fácilmente a tu entorno original anterior a la rebase con git log -g y / o git reset --hard ORIG_HEAD . Simplemente no haga forzar empujes (no permitido por defecto en casi todos los serveres de git) y usted estará feliz feliz.

EDITADO

Con el time, mi comprensión se ha expandido. git pull --rebase llama a git rebase para hacer el trabajo de rebase, por lo que en ese sentido no hay diferencia entre ellos. Sin embargo, git-pull realmente llama a git rebase --onto @{u} $(git merge-base HEAD @{u}@{1}) OK, esa syntax ("@ {u} @ {1}" es quizás es un poco opaco y es una simplificación para arrancar, pero el punto es que descubre cuál era la base de fusión hacia arriba ANTES de ejecutar el command de búsqueda. ¿Qué diferencia hace esto, preguntas? Bueno, en el caso normal ninguno. Sin embargo, si está cambiando hacia donde está apuntando la stream ascendente o si la stream ascendente misma fue reestadificada, bastantes. Si se reescribió el git rebase @{u} ascendente y luego se hizo un git rebase @{u} , podría estar muy descontento y podría tener compromisos dobles o conflictos dependiendo de cuánto se hayan reescrito los compromisos anteriores. Sin embargo, con la magia detrás de git pull --rebase solo se git pull --rebase las confirmaciones que son tuyas y las tuyas por sí solas encima de @ {u}.

OK, esto también es una simplificación. Si upstream hizo una rebase comenzando con los 100 commits atrás (pero en realidad hay más de 101 commits en la historia) e hiciste una git fetch antes de hacer un git pull --rebase entonces git no podrá determinar con precisión cuál es la combinación histórica correcta La base era averiguar cuáles son tus compromisos locales. El resultado de esto es que git fetch considera dañino (cuando tienes commits locales y upstream se reescriben). Sin embargo, la verdadera regla empírica es "nunca intente cambiar el historial después de haber sido compartido / publicado / presionado", que es donde comencé.

TL; DR:

git fetch considerado nocivo (así que use git pull --rebase ); y nunca intente cambiar el historial después de haber sido compartido / publicado / enviado (porque, entre otras cosas, causará que git fetch sea ​​dañino).

La verdad es que son diferentes. Aquí hay una página web realmente útil que lo explica maravillosamente:

http://gitolite.com/git-pull–rebase.html

Así que git pull --rebase tiene git pull --rebase magia sobre la git fetch; git rebase git fetch; git rebase que la mayoría de las veces no notarás, pero en los casos en que el mantenedor precavido ha ignorado maliciosamente todas esas advertencias severas y ha decidido reescribir el historial de una twig pública, realmente puede ayudarte consultando tu reflog local y haciendo la rebase local de una manera más inteligente.

Dicho esto, esto sigue siendo una rebase, ¡así que aún estás reescribiendo la historia! Por lo tanto, todas las advertencias de popa estándar aún se aplican. Pero si estás trabajando en una twig privada (es decir, no publicada), entonces está bien.

Diré un poco más sobre las severas advertencias. Son válidos, pero personalmente encuentro que la mayoría de la gente está un poco demasiado paranoica con la rebase, como un git rebase se git rebase en su dormitorio a mitad de la noche cuando eran pequeños y se comió a su hermana o algo así. Realmente no debería ser tan aterrador:

  • si se trata de una sucursal privada, rebase al contenido de su corazón
  • si es una sucursal pública, no vuelva a establecerla a less que realmente deba hacerlo, y si lo hace, asegúrese de comprender el impacto y asegúrese de que cualquier persona que pueda verse afectada reciba información adecuada sobre lo que ha hecho, para que no lo haga. get una desagradable sorpresa y perder un montón de time averiguar qué sucedió.

Es así de simple. Y sí, iría tan lejos como para alentar activamente a las personas a que git rebase -i regularmente git rebase -i en sus sucursales privadas. Pulir la historia antes de ir a algún lugar público / en sentido ascendente es algo bueno , porque nadie quiere pasar por la historia de un proyecto que está lleno de confirmaciones como "¡Uy !, corrigiendo un error que cometí hace 3 commits". (OTOH, no te obsesiones con el cambio de rumbo en busca de una historia impecable. Somos humanos. Cometemos errores. Hazlo).

Una última observación sobre el git pull --rebase magic. Si la twig pública ascendente ha sido networkingiseñada de una manera sensata (por ejemplo, aplastando / arreglando commits, o abandonando commits que no deberían haberse puesto allí) entonces la magia funciona a su favor. Sin embargo, si la rebase cadena arriba accidentalmente deja de comprometerse, entonces la magia evitará silenciosamente que usted los devuelva. En este caso, si desea volver a poner esos commits caídos, debería usar git fetch; git rebase git fetch; git rebase .

Además de actualizar su sucursal local desde su sucursal de seguimiento remoto, el command -pull actualiza sus files de espacio de trabajo.

Por lo tanto, probablemente sea más típico git pull –rebase (o configure pull para usar rebase por defecto) que git fetch; git rebase.