multiple - how to do cherry pick in git
¿Cómo git-cherry-pick solo cambia en ciertos archivos? (10)
Combine una rama en una nueva (squash) y elimine los archivos que no sean necesarios:
git checkout master
git checkout -b <branch>
git merge --squash <source-branch-with-many-commits>
git reset HEAD <not-needed-file-1>
git checkout -- <not-needed-file-1>
git reset HEAD <not-needed-file-2>
git checkout -- <not-needed-file-2>
git commit
Si quiero fusionarme en una rama Git, los cambios realizados solo en algunos de los archivos modificados en una confirmación en particular que incluye cambios en varios archivos, ¿cómo se puede lograr esto?
Supongamos que Git commit llamado stuff
tiene cambios en los archivos A
, B
, C
y D
pero quiero fusionar solo los cambios de stuff
los archivos A
y B
Suena como un trabajo para git cherry-pick
pero cherry-pick
solo sabe cómo combinar compromisos completos, no un subconjunto de los archivos.
Encontré otra forma que previene cualquier fusión conflictiva en la selección de cerebros en la cual IMO es algo fácil de recordar y entender. Dado que en realidad no está seleccionando un compromiso, sino que forma parte de él, primero debe dividirlo y luego crear un compromiso que se ajuste a sus necesidades y seleccionarlo.
Primero cree una rama desde la confirmación que desea dividir y compruebe:
$ git checkout COMMIT-TO-SPLIT-SHA -b temp
Luego revertir la confirmación anterior:
$ git reset HEAD~1
A continuación, agregue los archivos / cambios que desee para cherry-pick:
$ git add FILE
y cometerlo:
$ git commit -m "pick me"
note el hash de confirmación, llamémoslo PICK-SHA y regresemos a su rama principal, maestro, por ejemplo, forzando el pago:
$ git checkout -f master
y elige el compromiso:
$ git cherry-pick PICK-SHA
Ahora puedes borrar la rama temporal:
$ git branch -d temp -f
La selección de Cherry es elegir cambios de un "commit" específico. La solución más sencilla es elegir todos los cambios de ciertos archivos, usar
git checkout source_branch <paths>...
Por ejemplo:
$ git branch
* master
twitter_integration
$ git checkout twitter_integration app/models/avatar.rb db/migrate/20090223104419_create_avatars.rb test/unit/models/avatar_test.rb test/functional/models/avatar_test.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: app/models/avatar.rb
# new file: db/migrate/20090223104419_create_avatars.rb
# new file: test/functional/models/avatar_test.rb
# new file: test/unit/models/avatar_test.rb
#
$ git commit -m "''Merge'' avatar code from ''twitter_integration'' branch"
[master]: created 4d3e37b: "''Merge'' avatar code from ''twitter_integration'' branch"
4 files changed, 72 insertions(+), 0 deletions(-)
create mode 100644 app/models/avatar.rb
create mode 100644 db/migrate/20090223104419_create_avatars.rb
create mode 100644 test/functional/models/avatar_test.rb
create mode 100644 test/unit/models/avatar_test.rb
Fuentes y explicación completa http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/
ACTUALIZAR:
Con este método, git no MERGE el archivo, solo anulará cualquier otro cambio realizado en la rama de destino. Deberá combinar los cambios manualmente:
$ git diff HEAD nombre de archivo
Lo haría con cherry-pick -n
( --no-commit
) que le permite inspeccionar (y modificar) el resultado antes de cometer:
git cherry-pick -n <commit>
# unstage modifications you don''t want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD <path>
# commit; the message will have been stored for you by cherry-pick
git commit
Si la gran mayoría de las modificaciones son cosas que no desea, en lugar de verificar rutas individuales (el paso intermedio), puede restablecer todo de nuevo y luego agregar lo que desee:
# unstage everything
git reset HEAD
# stage the modifications you do want
git add <path>
# make the work tree match the index
# (do this from the top level of the repo)
git checkout .
Los otros métodos no funcionaron para mí ya que la confirmación tuvo muchos cambios y conflictos con muchos otros archivos. Lo que se me ocurrió fue simplemente
git show SHA -- file1.txt file2.txt | git apply -
En realidad, no add
los archivos ni realiza una confirmación por usted, por lo que es posible que deba hacer un seguimiento de ellos.
git add file1.txt file2.txt
git commit -c SHA
O si desea omitir la adición, puede usar el argumento --cached
para git apply
git show SHA -- file1.txt file2.txt | git apply --cached -
Por lo general, uso la -p
con un registro de git de la otra rama, que me parece más fácil y más granular que la mayoría de los otros métodos que he encontrado.
En principio:
git checkout <other_branch_name> <files/to/grab in/list/separated/by/spaces> -p
ejemplo:
git checkout mybranch config/important.yml app/models/important.rb -p
A continuación, aparece un cuadro de diálogo que le pregunta qué cambios desea en "blobs". Esto funciona bastante bien para cada parte del cambio de código continuo que luego puede señalar y
(Sí) n
(No), etc. para cada parte de código.
La opción -p
o patch
funciona para una variedad de comandos en git, incluyendo git stash save -p
que te permite elegir lo que quieres esconder de tu trabajo actual
A veces utilizo esta técnica cuando he trabajado mucho y me gustaría separarla y comprometerme en más confirmaciones basadas en temas usando git add -p
y elegir lo que quiero para cada confirmación :)
Quizás la ventaja de este método sobre la respuesta de Jefromi es que no tienes que recordar qué comportamiento de git reset es el correcto :)
# Create a branch to throw away, on which we''ll do the cherry-pick:
git checkout -b to-discard
# Do the cherry-pick:
git cherry-pick stuff
# Switch back to the branch you were previously on:
git checkout -
# Update the working tree and the index with the versions of A and B
# from the to-discard branch:
git checkout to-discard -- A B
# Commit those changes:
git commit -m "Cherry-picked changes to A and B from [stuff]"
# Delete the temporary branch:
git branch -D to-discard
Use git merge --squash branch_name
para obtener todos los cambios de la otra rama y preparará un compromiso para usted. Ahora elimine todos los cambios innecesarios y deje el que desee. Y Git no sabrá que hubo una fusión.
Yo solo escogería todo, luego haría esto:
git reset --soft HEAD^
Entonces revertiría los cambios que no quiero, y luego hago un nuevo compromiso.
La situación:
Usted está en su sucursal, digamos master
y tiene su compromiso en cualquier otra sucursal. Tienes que elegir un solo archivo de ese compromiso en particular.
El enfoque:
Paso 1: Checkout en la rama requerida.
git checkout master
Paso 2: Asegúrate de haber copiado el hash de confirmación requerido.
git checkout commit_hash path/to/file
Paso 3: Ahora tiene los cambios del archivo requerido en la rama deseada. Solo necesitas añadirlos y cometerlos.
git add path/to/file
git commit -m "Your commit message"