Tengo 57 sucursales locales. Sé que hice un cambio en cierto archivo en uno de ellos, pero no estoy seguro de cuál. ¿Existe algún tipo de comando que pueda ejecutar para encontrar qué ramas contienen cambios en un archivo determinado?
Respuestas:
Encuentra todas las ramas que contienen un cambio en NOMBRE DE ARCHIVO (incluso si están antes del punto de rama (no registrado))
FILENAME="<filename>"
git log --all --format=%H $FILENAME | while read f; do git branch --contains $f; done | sort -u
Inspeccione manualmente:
gitk --all --date-order -- $FILENAME
Encuentra todos los cambios en FILENAME no combinados con el maestro:
git for-each-ref --format="%(refname:short)" refs/heads | grep -v master | while read br; do git cherry master $br | while read x h; do if [ "`git log -n 1 --format=%H $h -- $FILENAME`" = "$h" ]; then echo $br; fi; done; done | sort -u
git log -Schange …o git log --grep LOGMESSAGE …(con… representando el resto del comando que mencioné)?
gitk --all -- filenameque le mostrará gráficamente todos los cambios en ese archivo. Si puede identificar el compromiso en cuestión, puede usarlo git branch --containspara ver a qué ramas ha migrado el compromiso. Si desea ver en qué rama se creó originalmente la confirmación en cuestión , busque en Google git-what-branch, pero tenga en cuenta que las fusiones de avance rápido pueden ocultar esa información.
git log --all --format='--contains %H' "$file" | xargs git branch
Todo lo que necesitas es
git log --all -- path/to/file/filename
Si desea conocer la rama de inmediato, también puede usar:
git log --all --format=%5 -- path/to/file/filename | xargs -I{} -n 1 echo {} found in && git branch --contains {}
Además, si tuvo algún cambio de nombre, es posible que desee incluir --followel comando de registro de Git.
--sourceallí y estará dorado.
Parece que esto sigue siendo un problema sin una solución adecuada. No tengo suficientes créditos para comentar, así que aquí está mi pequeña contribución.
La primera solución de Seth Robertson funcionó un poco para mí, pero solo me dio ramas locales, entre las cuales había muchos falsos positivos, probablemente debido a fusiones de la rama estable.
La segunda solución de Adam Dymitruk no funcionó para mí en absoluto. Para empezar, ¿qué es --format =% 5? No es reconocido por git, no pude encontrar nada al respecto y no pude hacer que funcione con otras opciones de formato.
Pero su primera solución combinada con la opción --source y con un simple grep resultó útil:
git log --all --source -- <filename> | grep -o "refs/.*" | sort -u
Esto me proporciona una serie de etiquetas y ramas remotas y una rama local, donde hice los últimos cambios en el archivo. No estoy seguro de cuán completo es esto.
ACTUALIZAR según la solicitud de @nealmcb, ordenando las ramas por cambio más reciente:
Primero, puede cambiar el grep a "refs / heads /.*", lo que le dará solo las ramas locales. Si solo hay unas pocas ramas, puede examinar la última confirmación de cada una de esta manera:
git log -1 <branch> -- <filename>
Si hay más ramas y realmente desea automatizar esto, puede combinar los dos comandos usando xargs, formato de registro de git y otro tipo en esta línea:
git log --all --source -- <filename> | grep -o "refs/heads/.*" | sort -u | xargs -I '{}' git log -1 --format=%aI%x20%S '{}' -- <filename> | sort -r
Esto dará como resultado una salida como esta:
2020-05-07T15:10:59+02:00 refs/heads/branch1
2020-05-05T16:11:52+02:00 refs/heads/branch3
2020-03-27T11:45:48+00:00 refs/heads/branch2
Sé que esta pregunta es antigua, pero seguí volviendo a ella antes de desarrollar mi propia solución. Siento que es más elegante y gracias al uso de la base de fusión se filtran las ramas no deseadas.
#!/bin/bash
file=$1
base=${2:-master}
b=$(tput bold) # Pretty print
n=$(tput sgr0)
echo "Searching for branches with changes to $file related to the $base branch"
# We look through all the local branches using plumbing
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
# We're establishing a shared ancestor between base and branch, to only find forward changes.
merge_base=$(git merge-base $base $branch)
# Check if there are any changes in a given path.
changes=$(git diff $merge_base..$branch --stat -- $file)
if [[ ! -z $changes ]]; then
echo "Branch: ${b}$branch${n} | Merge Base: $merge_base"
# Show change statistics pretty formatted
git diff $merge_base..$branch --stat -- $file
fi
done
Si lo coloca en PATH como git-find-changes(con permisos ejecutables), puede llamarlo congit find-changes /path
Salida de ejemplo para
git find-changes app/models/
Branch: update_callbacks | Merge base: db07d23b5d9600d88ba0864aca8fe79aad14e55b
app/models/api/callback_config.rb | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
Branch: repackaging | Merge base: 76578b9b7ee373fbe541a9e39cf93cf5ff150c73
app/models/order.rb | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
El siguiente es un método de fuerza bruta poco elegante, pero espero que funcione. Asegúrese de haber escondido primero los cambios no confirmados, ya que cambiará la rama en la que se encuentra actualmente.
for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
git checkout $branch && git grep SOMETHING
done
git log -S
for-each-refembargo, no estoy seguro de que aún respete esa shortbandera. Dicho esto, ignore mi respuesta; las otras respuestas son mejores.