Git aplastamiento falso

¿Hay algún problema con este flujo de trabajo para get un resultado similar de una calabaza?

  • Pagar una nueva twig del master llamada draft_feature_a
  • Haga un montón de commits. Algunos commits rompen código. Algunos tienen posts de compromiso descuidados.
  • Checkout master, y desde el pago maestro una nueva twig llamada feature_a
  • incorpore los cambios finales de la function borrador haciendo la git checkout draft_feature_a $(git diff --name-only master draft_feature_a)

Ahora solo tiene los cambios finales y puede asignar aquellos con un bonito post de compromiso.

No capturará eliminaciones de files, por ejemplo:

 $ git checkout draft_feature_a $(git diff --name-only master draft_feature_a) error: pathspec 'ttt.py' did not match any file(s) known to git. 

Puedes hacer lo mismo con un real-rebase-and-squash-etc (usé "fixup" a continuación, más o less lo mismo, en realidad, los commits originales aún se pueden ver en draft_feature_a ):

 $ git checkout -b draft_feature_a [work, commit, etc - I made two commits: add newfile and rm ttt.py] $ git checkout master Switched to branch 'master' $ git checkout -b feature_a Switched to a new branch 'feature_a' $ git merge draft_feature_a Updating 523bacb..3a486fc Fast-forward newfile | 0 ttt.py | 14 -------------- 2 files changed, 14 deletions(-) create mode 100644 newfile delete mode 100644 ttt.py git rebase -i master [edit to make everything but the first a "fixup"] ... 2 files changed, 14 deletions(-) create mode 100644 newfile delete mode 100644 ttt.py Successfully rebased and updated refs/heads/feature_a. $ git commit --amend [edit commit message] 

De hecho, utilizo mucho este tipo de flujos de trabajo, aunque la mayoría de las veces simplemente "git rebase -i" el borrador. Tenga en count que los commits originales están disponibles ya sea que haga o no una twig de "borrador" por separado, simplemente pierden su nombre y deben search en el reflog para encontrar el ID de confirmación. Puede agregar un nuevo nombre en lugar de crear una nueva twig y "git merge" -ing:

(Primero, limpiemos el ejemplo anterior)

 $ git checkout master Switched to branch 'master' $ git branch -D draft_feature_a Deleted branch draft_feature_a (was 3a486fc). $ git branch -D feature_a Deleted branch feature_a (was 0fc36f0). 

(ahora un nuevo ejemplo)

 $ git checkout -b feature_a Switched to a new branch 'feature_a' [work work work] [time to clean up, let's stick a label on this version so I can find it easily:] $ git branch messy_feature_a feature_a $ git rebase -i master 

Una vez que la rebase está list, con todo aplastado, arreglado, reorganizado, posts de compromiso editados, etc., si decido que arruiné algo, todo mi trabajo "borrador" (de baja calidad / desorderado) todavía está disponible por nombre bajo el nombre "desorderado". Cuando estoy satisfecho, y no quiero el nombre anterior, lo borro manualmente ( git branch -D ).

El truco para entender esto es que cada vez que haces cosas en git, solo agregas nuevas confirmaciones . Los antiguos se quedan en su repository hasta que (eventualmente) hagan algo implícito o explícito para "recogerlos". Siempre que tengan un nombre de label de twig (u otro nombre "visible", como una label) que haga que los commit sean 3a486fc por algo que no sea el 3a486fc SHA1 del estilo 3a486fc , durarán "para siempre". Eliminar una twig simplemente borra la label. Después de un mes o tres, los commits sin label finalmente son recolectados. (Más precisamente, todavía tiene un nombre en el reflog, hasta que caduque: las inputs de reflog tienen un límite de time. Consulte la documentation de git reflog , especialmente el --expire=<time> ).

Del mismo modo, una "rebase" hace una nueva serie de commits, dejando todos los commit anteriores allí. Cuando se completa la rebase, git quita la label del final de la serie de confirmaciones anteriores y la pega al final de la nueva serie de confirmaciones:

 A -- B -- C [label: master] \ D -- E [label: feature_a] [rebase feature_a on master, and squash or fixup to make commit DE which is D+E] A -- B -- C [label: master] | \ | D -- E [no label!] \ DE [label: feature_a] 

Si agrega una label adicional antes de hacer la rebase, la label feature_a twig actual se quita y se mueve a la (s) nueva (s) confirmación (es), pero la otra label ( messy_feature_a ) se messy_feature_a y le da fácil acceso a commit E, y por lo tanto toda la cadena (D y E ramificando C).

Parece que estás en un sistema con sabor a Linux $(git... Esto debería funcionar y se ocupará del file eliminado:

 git checkout -b feature_a master git diff draft_feature_a | patch -p1 -R 

Este es mi nuevo flujo de trabajo:

  • Pagar una nueva twig del master llamada draft_feature_a
  • Haga un montón de commits. Algunos commits rompen código. Algunos tienen posts de compromiso descuidados.
  • fusionar master en draft_feature_a , y resolver cualquier conflicto.
  • desde draft_feature_a checkout una nueva twig final_feature_a ( git checkout -b final_feature_a )
  • git reset --soft master
  • Ahora solo tiene los cambios finales y puede asignar aquellos con un bonito post de compromiso.

Sé que puedo hacer todo esto con un git rebase -i master y squashing, pero cuando hay conflictos se complican para mí.