Backport cambia de file renombrado

Tengo dos twigs: tronco, producción. He encontrado un problema en el maletero, lo arreglé y lo comprometí, lo empujé. Ahora fue probado y necesito fusionar los cambios en la twig de producción como un arreglo caliente. Intento usar el cherry-pick. Sin embargo, no funciona porque un file cambiado en la corrección se renombró anteriormente en el tronco durante algunas refactorizaciones que no quiero poner en producción.

No quiero fusionar todo, sino solo llevar este compromiso. La selección de cereza falla con el conflicto "eliminado por nosotros" (por supuesto, el nuevo file nunca existió en la twig de producción).

¿Cuál es la forma correcta de llevar los cambios al file anterior?

Usaría un buen parche viejo para esto:

git show COMMIT_ID -- old/file/name.txt | patch new/file/name.txt 

Si:

  • Esperaba / esperaba que Git detectara el movimiento o cambio de nombre del file en el tronco, pero no lo hizo, y no lo hizo.
  • Su repository tiene una cantidad razonable de files

… entonces definitivamente deberías considerar cambiar tu configuration de git así:

 $ git config merge.renameLimit 999999 

Es posible que durante un merge / cherry-pick, git llegue al límite de comprobación de files pnetworkingeterminado (creo que es 400 o 1000 o algo así) antes de que sea capaz de localizar la coincidencia de cambio de nombre adecuada. Al boost este límite, puede hacer que merge / cherry-pick tome más time mientras busca su file renombrado, pero puede ayudar a evitar desafíos de fusión "eliminados por nosotros".

Eso debería ser el truco, pero si el file renombrado era pequeño y los cambios entre las twigs son significativos, también podría jugar con la configuration de -X rename-threshold , por ejemplo, bajarla del 50% pnetworkingeterminado con -X rename-threshold=25%

Enfrentado con el mismo problema, le pregunté a un colega qué haría, y su respuesta instantánea fue:

 git checkout production git mv production-filename trunk-filename && git commit -m "Just fooling git" git cherry-pick trunk-commit git mv trunk-filename production-filename && git commit -m "Undo the damage" # Now squash the 3 commits git rebase -i HEAD~3 

Funcionó como un encanto para mí.

Para seleccionar cambios en cualquier cantidad de files, en el caso de un directory cambie el nombre entre las twigs:

 git diff ... | sed -e 's|<old dir>|<new dir>|' | git apply - 

Esto es un poco complicado. Por ejemplo, puede crear un parche desde un diff y aplicarlo al file anterior. Pero en el futuro para evitar estos problemas, recomendaría hacer arreglos en la twig de producción y probarla allí primero, luego fusionarla desde la producción a la troncal.

Experimento el mismo problema y he tratado de encontrar una solución.

Lo resolví usando una secuencia de rebases. No hice más testings que éstas, ¡así que utilícelas bajo su propio riesgo!

Si estás interesado, échale un vistazo en github:

https://github.com/fraschfn/cherry-pick

Hice una secuencia de commands de shell que intenta hacer una selección random mientras adivina movimientos de files (no funciona si cambió el nombre del file, solo si lo movió a otra carpeta): Sin embargo: actualmente fallará si se agrega la confirmación nuevos files o si él mismo cambia el nombre de los files.

 #!/bin/bash # # Attemps to guess file moves (rename of folders) when cherry-pick'ing. # Gaspard van Koningsveld # [ "$1" == "" ] && echo "usage: $0 <commit-hash-to-cherry-pick>" && exit 1 TMP_PATCH_FILE="temp-cherry-pick-patch" function abort() { echo "Aborting" "rm" -f "$TMP_PATCH_FILE" exit 1 } function main() { echo "Retreiving commit patch..." "git" show "$1" > "$TMP_PATCH_FILE" || abort echo "Matching renamed files..." sedcmds="" for oldfile in $("grep" -E '(--- a|\+\+\+ b)' "$TMP_PATCH_FILE" | "cut" -c 7- | "sort" | "uniq"); do [ -f "$oldfile" ] && continue renamefound=0 oldfilepart="$oldfile" while [ $renamefound -eq 0 ]; do possiblefiles=$("git" ls-files "**/$oldfilepart") if [ "$possiblefiles" != "" ]; then if [ $("wc" -l <<< "$possiblefiles") == "1" ]; then echo " $oldfile > $possiblefiles" sedcmds="$sedcmds s|/$oldfile|/$possiblefiles|g;" break else echo " ERROR: More than one rename possibility found for file $oldfile:" echo "$possiblefiles" abort fi fi prevoldfilepart="$oldfilepart" oldfilepart="${oldfilepart#*/}" if [ "$prevoldfilepart" == "$oldfilepart" ]; then echo " ERROR: Could not find rename for $oldfile." abort fi done done echo "Renaming files in patch..." "sed" -i "$sedcmds" "$TMP_PATCH_FILE" || abort echo "Applying patch as new commit..." "sed" -i "s/^commit /From commit /;s/^Author: /From: /" "$TMP_PATCH_FILE" || abort "git" am -3 "$TMP_PATCH_FILE" "rm" -f "$TMP_PATCH_FILE" } main "[email protected]"