2011-07-18 10 views
13

Digamos que tengo el siguiente historialgit historial de registro de simplificación

 D---E-------F 
    / \  \ 
     B---C---G---H---I---J 
    /     \ 
    A-------K---------------L--M 

git log---ancestry ruta D..M me dará

  E-------F 
      \  \ 
       G---H---I---J 
          \ 
          L--M 

Sin embargo, me gustaría simplemente el siguiente

  E 
      \  
       G---H---I---J 
          \ 
          L--M 

O

  E-------F 
        \ 
         I---J 
          \ 
          L--M 

Esencialmente, me gustaría recorrer solo una ruta, no dos.

¿Esto es posible? Y si es así, ¿cuál es el comando?

Editar:

He intentado usar --first-padres, pero esto no es exactamente la misma. git log G..M --first-padre me da

    F 
        \ 
        H---I---J 
          \ 
          L--M 

Incluye H, F, porque es el primer padre de I. En su lugar me gustaría

    H---I---J 
          \ 
          L--M 

Cualquier ayuda sería apreciado

solución (que trabajó para mí):

Como se ha indicado @VonC, no hay una sola de una sola línea que hace esto. Así que terminé usando un script bash.

  1. Para cada confirmación en 'git log---ancestry ruta G..M'
  2. determinar si $ comprometerse con los padres incluye el envío de datos que se encontraban antes en
  3. caso afirmativo, continuar. haz algo interesante
  4. Si no, omita ese compromiso.

Por ejemplo, git log-commit --first G..M es

H - F - I - J - L - M 

Sin embargo, el padre del F es E, H. Así no omitimos F, dándome

H - I - J - L - M 

¡Yay!

Respuesta

4

No creo que esto es directamente posible (a menos que sepa de antemano la lista exacta de incluir/excluir, que niega el propósito de caminar el DAG)

En realidad, el OP Ken Hirakawa logró que el esperado lineal de la historia por:

git log --pretty=format:"%h%n" --ancestry-path --reverse $prev_commit..$end_commit 

Y para cada confirmación, asegurándose de que es un hijo directo de la confirmación anterior.

Aquí está el script writtten by Ken Hirakawa.


Aquí está mi script para crear el DAG se menciona en la sección History Simplification de la página del manual de git log, para --ancestry-path:

Usted encontrará al final de la escritura del golpe que usé para crear una historia similar (llámalo con el nombre del directorio raíz y tu nombre de usuario).

defino:

$ git config --global alias.lgg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative" 

me sale:

$ git lgg 
* d7c4459 - (HEAD, M, fromA) M <VonC> 
* 82b011d - (L) Merge commit 'J' into fromA <VonC> 
|\ 
| * 190265b - (J, master) J <VonC> 
| * ef8e325 - (I) Merge commit 'F' <VonC> 
| |\ 
| | * 4b6d976 - (F, fromB) F <VonC> 
| * | 45a5d4d - (H) H <VonC> 
| * | 834b239 - (G) Merge commit 'E' <VonC> 
| |\ \ 
| | |/ 
| | * f8e9272 - (E) E <VonC> 
| | * 96b5538 - (D) D <VonC> 
| * | 49eff7f - (C) C <VonC> 
| |/ 
| * 02c3ef4 - (B) B <VonC> 
* | c0d9e1e - (K) K <VonC> 
|/ 
* 6530d79 - (A) A <VonC> 

A partir de ahí, no puedo excluir a uno de los padres de cometer I.

La ascendencia de la ruta no volver:

$ git lgg --ancestry-path D..M 
* d7c4459 - (HEAD, M, fromA) M <VonC> 
* 82b011d - (L) Merge commit 'J' into fromA <VonC> 
* 190265b - (J, master) J <VonC> 
* ef8e325 - (I) Merge commit 'F' <VonC> 
|\ 
| * 4b6d976 - (F, fromB) F <VonC> 
* | 45a5d4d - (H) H <VonC> 
* | 834b239 - (G) Merge commit 'E' <VonC> 
|/ 
* f8e9272 - (E) E <VonC> 

lo cual es consistente con la página del manual de registro:

Un habitual D..M computa un conjunto de confirmaciones que son ancestros de M, pero excluye a los que son ancestros de D.
Esto es útil para ver qué pasó con la historia que conduce a M desde D, en el sentido de que "lo que M tiene que no existía en D".
El resultado en este ejemplo serían todos los commits, excepto A y B (y D, por supuesto).

Cuando queremos averiguar lo que compromete en M están contaminados con el error introducido por D y necesitamos fijar, sin embargo, lo que se quiere ver sólo el subconjunto de D..M que son en realidad descendientes de D, es decir, excluyendo C y K.
Esto es exactamente lo que hace la opción --ancestry-path.


#!/bin/bash 

function makeCommit() { 
    local letter=$1 
    if [[ `git tag -l $letter` == "" ]] ; then 
    echo $letter > $root/$letter 
    git add . 
    git commit -m "${letter}" 
    git tag -m "${letter}" $letter 
    else 
    echo "commit $letter already there" 
    fi 
} 

function makeMerge() { 
    local letter=$1 
    local from=$2 
    if [[ `git tag -l $letter` == "" ]] ; then 
    git merge $from 
    git tag -m "${letter}" $letter 
    else 
    echo "merge $letter already done" 
    fi 
} 

function makeBranch() { 
    local branch=$1 
    local from=$2 
    if [[ "$(git branch|grep $1)" == "" ]] ; then 
    git checkout -b $branch $from 
    else 
    echo "branch $branch already created" 
    git checkout $branch 
    fi 
} 

root=$1 
user=$2 
if [[ ! -e $root/.git ]] ; then 
    git init $root 
fi 
export GIT_WORK_TREE="./$root" 
export GIT_DIR="./$root/.git" 
git config --local user.name $2 

makeCommit "A" 
makeCommit "B" 
makeCommit "C" 
makeBranch "fromB" "B" 
makeCommit "D" 
makeCommit "E" 
makeCommit "F" 
git checkout master 
makeMerge "G" "E" 
makeCommit "H" 
makeMerge "I" "F" 
makeCommit "J" 
makeBranch "fromA" "A" 
makeCommit "K" 
makeMerge "L" "J" 
makeCommit "M" 
+0

no creo que le va a gustar la respuesta, pero hay un punto fundamental que debe ser entendido: un registro lineal no funciona muy bien con git porque no es lineal desarrollo. Esto es desafortunado para las personas que desean conocer todos los cambios que entraron en una rama, como por ejemplo cuando intenta producir un archivo ChangeLog. Producir archivos ChangeLog de git con mucha fusión realmente no funciona del todo, porque un archivo ChangeLog es un historial lineal, y el desarrollo no. –

+1

@Wes: sí, Git es un administrador de * content *, y si el contenido (de commits accesibles entre dos commits) es el resultado de una fusión, me sorprendería que un log, retrocediendo el DAG, pudiera ignorar parte si la historia que contribuyó a dicho contenido. – VonC

+1

Estoy totalmente de acuerdo en que ambos, pero supongo que no tener una sola línea para esto no es algo de lo que sorprenderse. Voy a aceptar la respuesta de VonC porque responde mi pregunta, pero edité la pregunta para incluir la solución que se me ocurrió. Por favor, eche un vistazo –

Cuestiones relacionadas