¿Hay alguna manera de agregar un solo file a múltiples twigs (locales) a la vez?

Supongamos que tengo un file que accidentalmente olvidé rastrear en git , como Foo.sh Después de desarrollar por un time, me doy count de que necesito que este file sea rastreado por git .

Sin embargo, dado que el file hasta ahora no se ha rastreado, si lo agrego a una twig en particular Branch1 y Branch1 una confirmación, desaparecerá cuando revise otra twig.

Mi solución actual a este problema es

  1. Foo.sh en Branch1 .
  2. Verifique cada sucursal que no sea Branch1 , y haga una git checkout Branch1 -- Foo.sh
  3. Ejecute git commit -m "Added Foo.sh" en cada twig que no sea Branch1 .

¿Hay una manera más directa de resolver este problema, suponiendo que no me importa si el post de confirmación es el mismo en todas las twigs?

El método de Vlad Nikitin funcionará, aunque puedes simplificarlo identificando el compromiso de seleccionar por el nombre de la sucursal:

 $ git checkout branch1 ... add and commit file ... ... at this point, "git show" will show that there's just the one change, which is to add Foo.sh ... $ for b in branch2 branch3 branch4; do > git checkout $b && git cherry-pick branch1 > done 

Como este es un file nuevo que no está presente en ninguna de las twigs enumeradas, no debería haber conflictos aquí.


Sin embargo, si (esto es muy grande si ) no ha publicado ninguno de los nuevos commits, es posible que desee "reescribir su historial" un poco, haciendo que parezca que puso Foo.sh antes, antes de que las twigs divergieran:

 A---B---C---D <-- branch1 |\ | E <-- branch2 \ F---G <-- branch3 

Si pudieras modificar la confirmación B para que contenga el nuevo Foo.sh , todas las confirmaciones "después" B también contendrán Foo.sh

En realidad, no puedes modificar B , pero puedes hacer un nuevo compromiso, B' , que es "como B pero también agrega Foo.sh ". Luego puedes copyr C a G a los nuevos commits C' a G' , basándolos en B' . Para hacer esto, reviso commit B por hash-ID para get un "HEAD separado", agrego el file y hago un git commit --amend :

 $ git checkout 1234567 ... git warns about detached HEAD ... ... create Foo.sh, make sure it's right ... $ git add Foo.sh $ git commit --amend ... editor ... [detached HEAD 278c036] ... N files changed, NN insertions(+) create mode 100755 Foo.sh create mode 100644 blah.txt ... 

Ahora, para mayor comodidad y protección, me gustaría un nombre temporal para este nuevo compromiso B' , así que:

 $ git tag temp_new_base 

y me acabo de dar count de que tampoco me gustaría escribir el hash para B , así que:

 $ git tag temp_old_base 1234567 

(Debería haber hecho esto antes de git commit --amend , pero lo olvidé, así que lo hago aquí en vez dando la ID de hash nuevamente).

Esto es lo que tengo ahora como una image:

  ____----temp_old_base . A---B---C---D <-- branch1 | |\ | | E <-- branch2 \ \ \ F---G <-- branch3 \ B' .____ ----temp_new_base 

Ahora todo lo que tengo que hacer es reubicar cada cadena "después de B " en cada una de las tres twigs, en la nueva confirmación B' . Aquí es donde entran las tags que acabo de agregar:

 $ git checkout branch1 $ git rebase --onto temp_new_base temp_old_base.. 

Esto copy C y D para hacer commits C' y D' , agregándolos a cometer B' . Los dos trucos aquí están usando --onto temp_new_base , diciéndole a rebase que haga crecer la nueva cadena de compromiso comenzando en commit B' ; y usando temp_old_base.. , lo que significa temp_old_base..HEAD , que significa "todo en HEAD que no está también en temp_old_base ", lo que significa que confirma C y D en este caso.

Cuando termine esa rebase, solo necesito repetir para las dos twigs restantes:

 $ git checkout branch2 $ git rebase --onto temp_new_base temp_old_base.. 

Esta vez, HEAD es branch2 que identifica commit E , por lo que temp_old_base.. significa rebase simplemente commit E

Por último, tengo que repetir esto para branch3 , después de lo cual puedo git tag -d las dos tags temporales.

(De hecho, dado que las tres twigs originales crecen desde el mismo punto-commit B , que etiqueté temp_old_base -y el command rebase es el mismo para las tres, puedo hacer lo mismo for b in branch1 branch2 branch3; do ... .bucle-con el command rebase en su lugar, esta vez-en cuanto a Cherry-picking Foo.sh en el extremo de cada twig. Todo esto depende del hecho de que sé que todas las twigs "salen de B ").


1 "¡Hah! ¡Todo! ¡ Todo , dice!" En serio, esta es la parte fácil. La parte difícil es identificar el punto en el que "deslizarse" en Foo.sh , y asegurarse de que ninguna de las confirmaciones a partir de allí se publique. Si se publican, no hagas esto. (Bueno, no lo hagas a less que realmente sepas lo que estás haciendo, y todo lo anterior es obvio para ti, porque tendrás que ayudar a todos los que tomaron las confirmaciones publicadas a recuperarse de esto).

Necesitas el command chery-pick

 $ git add file $ git commit -m 'file added' 

hacer git log para ver el hash de la confirmación

 $ git checkout another_branch $ git cherry-pick 'hash' $ git checkout another_branch2 $ git cherry-pick 'hash'