¿Cómo replicar git-checkout usando solo comandos de plomería?

4 minutos de lectura

avatar de usuario
Jack O´Connor

Me gustaría evitar llamar a los comandos de porcelana de mis guiones, pero ¿hay alguna manera de obtener algo del comportamiento de git checkout <commit> usando solo comandos de plomería como checkout-index? Estoy particularmente interesado en el efecto sobre la copia de trabajo: suponiendo que todo esté limpio, checkout elimina archivos que fueron rastreados en el antiguo HEAD y ausentes en el nuevo. checkout-index no parece tener ningún concepto de eliminación de archivos. Lo más parecido que se me ocurre sería llamar

git diff-tree -p <old> <new> | git apply

pero calcular toda la diferencia parece innecesariamente costoso. ¿Hay una mejor manera?

  • Cualquier razón por la que no llames git checkout ...?

    –Oliver Charlesworth

    23 de julio de 2014 a las 21:47

  • Sí, no hagas tu vida innecesariamente difícil.

    – ThiefMaster

    23 de julio de 2014 a las 21:56

  • En última instancia, quiero tener más control sobre cómo se realiza el pago. Por ejemplo, checkout puede eliminar archivos ignorados, y quiero evitar hacerlo (mayor seguridad). Pero quiero allanar archivos eliminados (seguridad disminuida), sin usar --force pavimentar todo. Esto es parte de un script que usa git debajo de las cubiertas para almacenar árboles de archivos, y checkout está muy cerca de cómo quiero que se comporte mi script, pero no del todo. Pensé que si podría conseguir checkout con los comandos de plomería podría ajustarlo desde allí, aunque avíseme si hay otra forma de obtener este control.

    – Jack O´Connor

    23 de julio de 2014 a las 22:07


  • ¿De verdad has probado eso diff-tree ¿es lento? checkout básicamente diferencia todo para averiguar qué hacer en primer lugar. (Por supuesto, checkout no crea parches y luego los aplica, y probablemente tú tampoco deberías hacerlo).

    –Edward Thomson

    23 de julio de 2014 a las 23:52


  • @EdwardThomson diff-tree es probablemente lo que quiero, pero no estoy seguro de en qué canalizar su salida. ¿Hay alguna forma de aplicar esta diferencia a la copia de trabajo además de la git apply hackear arriba? Sería bastante fácil escribir una secuencia de comandos de Python para tomar la lista de eliminaciones y realizarlas, pero me preocupa que sea lento.

    – Jack O´Connor

    24 de julio de 2014 a las 7:57

Estas buscando el dos arbol git read-tree -um. Utiliza un árbol base, (generalmente lo alimentas HEAD), un árbol de destino e (implícitamente) el índice y el árbol de trabajo. La tabla que describe su comportamiento fue difícil de entender para mí, así que tengo mi propia hoja de trucos, una reformateada que tiene más sentido para mí, de todos modos. En cualquier caso, implementa git checkout.

git read-tree -um H M  # `I` is the (implicit) index, GIT_INDEX_FILE

                    Legend

        H       Original tree (usually HEAD:)
        I       Indexed tree
        M       Merge target tree

        H->I     \
        H->M      } status in second relative to first
        I->M     /

        "-"     file exists in neither
       new      exists only in second
       deleted  exists only in first
       same     exists in both, unchanged
       changed  exists in both, different
      (blank)   irrelevant or all cases not otherwise given

        keep    keep current version
        fail    whole command fails, no changes
       delete   delete worktree file


      H->I      H->M      I->M

                          same     keep

     deleted   changed             fail
     deleted   deleted             delete
     deleted    same               delete unless Index empty, else use M
                same               keep

      same     changed             worktree clean: use M; dirty: fail
      same     deleted             worktree clean: deleted; dirty: fail

      new        -                 keep
      new       new      changed   fail
     changed   changed   changed   fail
     changed   deleted             fail


note: "index empty" identifies an initial checkout, where HEAD has been
set but never loaded.  git can't currently distinguish between a
delete-everything index and an initial-checkout index.

  • +1. Me gusta la hoja de trucos. He completado mi propia respuesta con un ejemplo usando git read-tree -um.

    – VoC

    28 de julio de 2014 a las 5:59

  • ¡Gracias! Nunca lo hubiera adivinado.

    – Jack O´Connor

    29 de julio de 2014 a las 16:07

  • De nada. Tampoco lo habría adivinado, no siempre es fácil ver lo que puedes hacer que git haga. Sé que realmente no obtuve este comando hasta que me enojé con la tabla en el documento y pasé el tiempo para hacer el mío.

    – jthill

    29 de julio de 2014 a las 16:43

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad