Preguntas de flujo de trabajo de Git y rebase vs fusión

He estado usando Git ahora durante un par de meses en un proyecto con otro desarrollador. Tengo varios años de experiencia conSVN, así que supongo que llevo mucho equipaje a la relación.

He oído que Git es excelente para ramificar y fusionar, y hasta ahora, simplemente no lo veo. Claro, la ramificación es muy simple, pero cuando trato de fusionarme, todo se va al infierno. Ahora, estoy acostumbrado a eso desde SVN, pero me parece que acabo de cambiar un sistema de versiones por debajo del par por otro.

Mi compañero me dice que mis problemas surgen de mi deseo de fusionarme de todas formas, y que debería usar rebase en lugar de fusionar en muchas situaciones. Por ejemplo, aquí está el flujo de trabajo que ha establecido:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature

Esencialmente, cree una rama de características, SIEMPRE rebase de maestro a rama y fusione de la rama de nuevo a maestro. Es importante tener en cuenta que la sucursal siempre permanece local.

Aquí está el flujo de trabajo con el que comencé

clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch

Hay dos diferencias esenciales (creo): siempre uso la combinación en lugar de la reorganización, y empujo mi rama de características (y mis confirmaciones de ramas de características) al repositorio remoto.

Mi razonamiento para la rama remota es que quiero hacer una copia de seguridad de mi trabajo mientras estoy trabajando. Nuestro repositorio se respalda automáticamente y se puede restaurar si algo sale mal. Mi computadora portátil no es, o no tan a fondo. Por lo tanto, odio tener código en mi computadora portátil que no se refleje en otro lugar.

Mi razonamiento para la fusión en lugar de rebase es que la fusión parece ser estándar y rebase parece ser una característica avanzada. Mi intuición es que lo que estoy tratando de hacer no es una configuración avanzada, por lo que el rebase debería ser innecesario. Incluso he leído el nuevo libro de programación pragmática en Git, y cubren la fusión extensamente y apenas mencionan rebase.

De todos modos, estaba siguiendo mi flujo de trabajo en una sucursal reciente, y cuando intenté fusionarlo de nuevo con master, todo se fue al infierno. Hubo toneladas de conflictos con cosas que no deberían haber importado. Los conflictos simplemente no tenían sentido para mí. Me llevó un día resolver todo, y finalmente culminó en un empuje forzado hacia el maestro remoto, ya que mi maestro local resolvió todos los conflictos, pero el remoto aún no estaba contento.

¿Cuál es el flujo de trabajo "correcto" para algo como esto? Se supone que Git hace que la ramificación y la fusión sean súper fáciles, y simplemente no lo veo.

Actualización 15/04/2011

Esta parece ser una pregunta muy popular, así que pensé en actualizar con mis dos años de experiencia desde la primera vez que pregunté.

Resulta que el flujo de trabajo original es correcto, al menos en nuestro caso. En otras palabras, esto es lo que hacemos y funciona:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature

De hecho, nuestro flujo de trabajo es un poco diferente, como solemos hacerfusiones de calabaza en lugar de combinaciones sin procesar. (Nota: Esto es controvertido, ver más abajo.) Esto nos permite convertir toda nuestra rama de características en un solo commit en master. Luego eliminamos nuestra rama de características. Esto nos permite estructurar lógicamente nuestros commits en master, incluso si son un poco desordenados en nuestras ramas. Entonces, esto es lo que hacemos:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature

Controversia de fusión de squash - Como han señalado varios comentaristas, la combinación de squash eliminará todo el historial en su rama de características. Como su nombre lo indica, aplasta todos los commits en uno solo. Para características pequeñas, esto tiene sentido ya que lo condensa en un solo paquete. Para funciones más grandes, probablemente no sea una gran idea, especialmente si sus confirmaciones individuales ya son atómicas. todo se reduce a la preferencia personal.

Github y Bitbucket (¿otros?) Solicitudes de extracción - En caso de que se pregunte cómo se relaciona la fusión / rebase con las solicitudes de extracción, le recomiendo que siga todos los pasos anteriores hasta que esté listo para volver a fusionarse con el maestro. En lugar de fusionarse manualmente con git, solo acepta el PR. Tenga en cuenta que esto no hará una fusión de squash (al menos no de manera predeterminada), pero no es squash ni avance rápido es la convención de fusión aceptada en la comunidad Pull Request (que yo sepa). Específicamente, funciona así:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin

He llegado a amar a Git y nunca quiero volver a SVN. Si estás luchando, solo quédate con él y eventualmente verás la luz al final del túnel.

Respuestas a la pregunta(10)

Su respuesta a la pregunta