Diferencia entre git pull y git pull --rebase

311

Comencé a usar git en algún momento y no entiendo completamente las complejidades. Mi pregunta básica aquí es averiguar la diferencia entre una git pully git pull --rebase, dado que la adición de la --rebaseopción no parece que hacer algo muy diferente: sólo lo hace un tirón.

Por favor, ayúdame a entender la diferencia.

Rndm
fuente
3
Posible duplicado de git pull VS git fetch git rebase
TJ
Enlace útil
Taras Melnyk

Respuestas:

326

git pull= git fetch+ git mergecontra el seguimiento de la rama aguas arriba

git pull --rebase= git fetch+ git rebasecontra el seguimiento de la rama aguas arriba

Si quieres saber cómo git mergey git rebasediferir, lee esto .

mvp
fuente
12
Vale la pena señalar que decir git pull --rebasees lo mismo git fetchy git rebasees básicamente cómo es, pero no es exactamente semánticamente equivalente. Hay algunas diferencias, algunas de las cuales se explican aquí. gitolite.com/git-pull--rebase
w0rp
8
Es lo que yo llamaría una "mentira conveniente", tomar prestada una frase de Scott Meyers. Es una buena manera de explicarlo independientemente.
w0rp
Muy corto. No puedo entender la diferencia. ¿Qué es tan importante fetch?
Verde
240

A veces tenemos un flujo ascendente que rebase / rebobina una rama de la que dependemos. Esto puede ser un gran problema, ya que nos genera conflictos desordenados si estamos aguas abajo.

La magia es git pull --rebase

Un git pull normal es, en términos generales, algo como esto (usaremos un origen remoto llamado y una rama llamada foo en todos estos ejemplos):

# assume current checked out branch is "foo"
git fetch origin
git merge origin/foo

A primera vista, puede pensar que un git pull --rebase hace exactamente esto:

git fetch origin
git rebase origin/foo

Pero eso no ayudará si el rebase ascendente involucró algún "aplastamiento" (lo que significa que los identificadores de parche de los commits cambiaron, no solo su orden).

Lo que significa git pull --rebase tiene que hacer un poco más que eso. Aquí hay una explicación de lo que hace y cómo.

Digamos que su punto de partida es este:

a---b---c---d---e  (origin/foo) (also your local "foo")

El tiempo pasa, y has hecho algunas confirmaciones además de tu propio "foo":

a---b---c---d---e---p---q---r (foo)

Mientras tanto, en un ataque de rabia antisocial, el mantenedor corriente arriba no solo ha rebajado su "foo", sino que incluso usó una calabaza o dos. Su cadena de compromiso ahora se ve así:

a---b+c---d+e---f  (origin/foo)

Un tirón git en este punto daría lugar al caos. Incluso una git fetch; git rebase origin / foo no lo cortaría, porque comete "b" y "c" por un lado, y comete "b + c" por el otro, entraría en conflicto. (Y de manera similar con d, e, y d + e).

Lo git pull --rebaseque, en este caso, es:

git fetch origin
git rebase --onto origin/foo e foo

Esto te da:

 a---b+c---d+e---f---p'---q'---r' (foo)

Aún puede obtener conflictos, pero serán conflictos genuinos (entre p / q / r y a / b + c / d + e / f), y no conflictos causados ​​por b / c en conflicto con b + c, etc.

Respuesta tomada de (y ligeramente modificada):
http://gitolite.com/git-pull--rebase

Mauri Lopez
fuente
99
Esta es la mejor respuesta. Es posible que desee cambiar el resultado final a---b+c---d+e---f---p'---q'---r' (foo)ya que el rebase cambia los hashes.
Bastien
22
Esta respuesta fue copiada y pegada literalmente de gitolite.com/git-pull--rebase y debe incluir la atribución según la licencia en esa página.
Comodín el
Esta es una gran explicación. Pero tuve una situación en la que me comprometí A, y envié un RP al repositorio aguas arriba que fue aceptado. Luego, cuando lo hice git pull --rebasecontra el repositorio ascendente, no obtuve una nueva A'confirmación además del repositorio ascendente retirado. De hecho, no A'existía en absoluto. ¿Es esto porque Ase fusionó con el sistema? ¿O es porque no hubo diferencia entre el upstream y mi versión rebase?
CMCDragonkai
Actualmente estoy revisando el tutorial de Git y estaba usando esta respuesta para comprender mejor a git pull --rebase. Pero una cosa que me confunde en esta situación hipotética es que el responsable del mantenimiento ha cambiado el historial del proyecto que ya se ha incorporado a los repositorios de desarrolladores locales. ¿No es solo una mala práctica en general? Si quisiera aplastar los commits / reescribir el historial, debería haberlo hecho antes de integrarlo en el repositorio central para evitar este tipo de conflictos.
bmcentee148
44

Supongamos que tiene dos confirmaciones en la sucursal local:

      D---E master
     /
A---B---C---F origin/master

Después de "git pull", será:

      D--------E  
     /          \
A---B---C---F----G   master, origin/master

Después de "git pull --rebase", no habrá punto de fusión G. Tenga en cuenta que D y E se convierten en confirmaciones diferentes:

A---B---C---F---D'---E'   master, origin/master
Deqing
fuente
1
¿No es A --- B --- C --- D '--- E' - F?
prgmrDev
55
@prgmrDev ¿Por qué se insertarían D y E antes que F?
Jon
1
¿No es exactamente lo que git rebasehace? Pero estamos hablando de eso git pull --rebase. Y son cosas diferentes.
Verde
10

En el caso más simple de no colisiones

  • con rebase: reajusta sus confirmaciones locales en la parte superior de HEAD remoto y no crea una confirmación de fusión / fusión
  • sin / normal: combina y crea una confirmación de fusión

Ver también:

man git-pull

Más precisamente, git pull ejecuta git fetch con los parámetros dados y llama a git merge para fusionar las cabezas de rama recuperadas en la rama actual. Con --rebase, ejecuta git rebase en lugar de git merge.

Ver también: ¿
Cuándo debo usar git pull --rebase?
http://git-scm.com/book/en/Git-Branching-Rebasing

drahnr
fuente
3
¿Y en caso de colisiones?
Rndm
1
Usted recibirá el pedido para resolver de forma manual y luego - continuar usando rebase: git sdd modified-file; git rebase --continueo fusión: git add modified-file; git commit;donde modified-filees su archivo local que modificar manualmente / mergetool
drahnr
¿Qué tiene de especial fetch? ¿Por qué crearon dos rebaseflujos? 1) git rebasey 2) git pull --rebase?
Verde
7

Para esto es importante entender la diferencia entre Merge y Rebase.

Las bases son cómo deben pasar los cambios desde la parte superior de la jerarquía hacia abajo y las fusiones son cómo fluyen hacia arriba.

Para más detalles, consulte: http://www.derekgourlay.com/archives/428

Sagar Mody
fuente
Creo que su respuesta ofrece una explicación mucho más simple que no es obvia en el resto de las respuestas anteriores. Gracias.
Aaron C