¿Cómo veo un diff desde untracked, unstaged, staged y commit changes todo contra el control remoto?

Así que tengo un master que es la línea de base, y tengo una situación arbitraria en la máquina del desarrollador que incluye:

  • files sin seguimiento
  • cambios sin escena
  • cambios escalonados
  • confirmaciones locales

¿Hay alguna manera de ver una diferencia de todo lo anterior con respecto al control remoto?

No como un solo command, pero siempre que tenga acceso a la máquina del desarrollador y tenga acceso al otro repository, sí. Simplemente llamemos a la máquina M del desarrollador y supongamos que en M , el acceso al repository "principal" se realiza a través del origin , es decir, el desarrollador ejecutó git clone <url> originalmente para crear el repository que ahora está en M.

El primer paso es asegurarse de que el repository en M esté actualizado con el repository en el otro sistema. Supongamos que M$ es el post en la máquina M cuando está en el clon:

 M$ git fetch origin 

El repository en M ahora tiene:

  • todos sus compromisos locales;
  • los files escalonados, en el índice;
  • los files sin escena, en el tree de trabajo;
  • cualquier file sin seguimiento, en el tree de trabajo;
  • todos los commits disponibles en origin

Ahora M tiene todo lo necesario para generar cualquier dificultad que desee, y la pregunta es: ¿Cómo le gustaría que se generaran y presentaran estas diferencias?

Supongamos además que estamos interesados ​​en:

  • Cualquier compromiso en la twig local B que no está en origin/B :

     ...--o--o--*--G--H <-- B \ J--K--L <-- origin/B 

    Aquí hay dos confirmaciones de este tipo, con hashes G y H

    Puede git show cada confirmación, para get un post de logging y un parche. O bien, puede ejecutar git format-patch <options> origin/B..B , para producir files de parche individuales (el valor pnetworkingeterminado) o un flujo stdout ( --stdout ) que contiene cada confirmación como un parche. Tenga en count que el format-patch no mostrará las confusiones de fusión y las diffs de las confusiones de fusión son complicadas de hacer, así que las ignoraremos.

    Si el repository se encuentra actualmente en la twig B (para que B sea HEAD ), puede ejecutar git format-patch <options> origin/B : el valor pnetworkingeterminado para format-patch es tratar un único argumento como <argument>..HEAD Por lo tanto:

     M$ git format-patch --stdout origin/B > /tmp/commits 
  • La diferencia entre la punta de la twig B (confirmar H ) y lo que está en el índice / área de ensayo. Supongamos, una vez más, que HEAD nombra a la twig B para facilitar esto:

     git diff --cached > /tmp/tip-to-staged 

    Esto escribe el diff a la salida estándar.

  • La diferencia entre lo que está en el índice y lo que está en el tree de trabajo:

     git diff > /tmp/staged-to-work-tree 

    Esto escribe el diff a la salida estándar.

  • La diferencia entre "nada" (un tree vacío) y cada file sin seguimiento. Este es el más difícil de get de Git, y también en cierto sentido el más tonto, ya que la diferencia entre "nada" y "algún set de files" es simplemente "algún set de files". No hay un único command de Git para generar esto, pero puedes usar git ls-files --other para get la list de dichos files y luego envolverlos como quieras. Alternativamente, podrías escribirlos en un commit; vea abajo.

  • Archivos que no solo no se han rastreado, sino que también se han ignorado. (Tenga en count que enumerar un file rastreado como ignorado no tiene ningún efecto en el file rastreado: dicho file se rastrea y no se ignora. "Ignorado" es un estado que se aplica solo a un file que también está, ya, sin seguimiento. En cualquier caso " sin seguimiento "simplemente significa" no en el índice ".) Esto es lo mismo que los files sin seguimiento en el punto anterior: simplemente los dividimos en" sin seguimiento e ignorado "frente a" sin seguimiento y sin ignorar ". De hecho, si elige usar git ls-files --other , obtiene todos los files sin seguimiento, incluidos los ignorados, a less que agregue la --exclude-standard .

Usando git stash save para que no se rastree o todos los files

Tenga en count que hemos tenido que usar al less tres commands de Git:

 git format-patch git diff --cached git diff 

y aún no tenemos los files sin seguimiento y / o ignorados. Si usamos git stash save , podemos get el último. Incluso podríamos lanzar uno (pero solo uno) git diff y agregar al less otro git diff . Sin embargo, otras cosas se vuelven más complejas. En particular, git stash save no hace nada si no hay nada que esconder, y debemos verificar esto:

 M$ old_stash=$(git rev-parse -q --verify refs/stash) M$ git stash save --untracked # assuming you do not want ignonetworking files M$ new_stash=$(git rev-parse -q --verify refs/stash) M$ [ "$new_stash" != "$old_stash" ] && have_stash=true || have_stash=false 

Si desea todos los files (sin seguimiento + ignorado), use --all lugar de --untracked .

También necesitamos la identificación hash del tree vacío :

 M$ empty_tree=$(git hash-object -t tree /dev/null) 

Ahora podemos get el diff del tree vacío al commit que contiene los --untracked -less-ignonetworking ( --untracked ) o untracked-including-ignonetworking ( --all ):

 M$ ($have_stash && git diff $empty_tree ${new_stash}^3) > /tmp/extra M$ $have_stash && git stash pop 

Ahora es seguro generar las otras diferencias, o puedes hacerlo antes de save el escondite y quizás explotar. (Y si convierte lo anterior en un guión, hay forms un tanto less torpes de escribirlo).

Si solo quieres un solo diff

Si no está interesado en preservar las confirmaciones individuales, puede ejecutar una única git diff de commit * o commit L en el diagtwig original anterior. (Si no hay nuevas confirmaciones en origin/branch estas son la misma confirmación.) Esto no mostrará lo que está en el índice (en etapas) o en el tree de trabajo (sin escena), por supuesto. Como antes, puede jugar algunos trucos con git stash save para realizar commits desde el índice y el tree de trabajo y (opcionalmente) --untracked o --untracked files. Como el compromiso del tree de trabajo de esta acción es, internamente, una confirmación de fusión, debe diferenciarla manualmente contra el padre interesante. Como antes, los files sin seguimiento se deben diferenciar contra un tree vacío.