comando git para hacer una rama como otra

Resuelto Arne Claassen asked hace 13 años • 9 respuestas

Estoy tratando de tomar una rama con cambios y devolverla para que sea idéntica a la anterior de la que se separó. Los cambios son locales y se han enviado a github, por lo que ninguno git resetde los dos git rebasees realmente viable, ya que cambian la historia, lo cual es malo con una rama que ya ha sido enviada.

También probé git mergecon varias estrategias, pero ninguna de ellas deshace los cambios locales, es decir, si hubiera agregado un archivo, una combinación podría volver a alinear otros archivos, pero aún tendré ese archivo que el upstream no tiene. tener.

Podría simplemente crear una nueva rama fuera del flujo ascendente, pero realmente me gustaría una combinación que, en términos de historial de revisiones, aplique todos los cambios para tomar mi rama y hacerla idéntica al flujo ascendente nuevamente, para que pueda impulsar ese cambio de manera segura. sin darle una paliza a la historia. ¿Existe tal comando o serie de comandos?

Arne Claassen avatar Feb 06 '11 12:02 Arne Claassen
Aceptado

Puede fusionar su rama ascendente con su devrama, con un controlador de combinación personalizado, "keepTheirs" :
consulte " " git merge -s theirs" necesario, pero sé que no existe ".
En su caso, sólo .gitattributessería necesario uno y un keepTheirsscript como:

mv -f $3 $2
exit 0

git merge --strategy=theirsSimulación #1

Se muestra como una combinación, con upstream como primer padre.

Jefromi menciona (en los comentarios) merge -s ours, fusionando su trabajo en el flujo ascendente (o en una rama temporal comenzando desde el flujo ascendente), y luego avanzando rápidamente su rama hasta el resultado de esa fusión:

git checkout -b tmp origin/upstream
git merge -s ours downstream         # ignoring all changes from downstream
git checkout downstream
git merge tmp                        # fast-forward to tmp HEAD
git branch -D tmp                    # deleting tmp

Esto tiene la ventaja de registrar el antecesor ascendente como el primer padre, de modo que la fusión signifique "absorber esta rama de tema desactualizada" en lugar de "destruir esta rama de tema y reemplazarla con ascendente" .

Actualización 2023: por ejemplo, si desea mainreflejar exactamente qué deves:

git switch -c tmp dev
git merge -s ours main   # ignoring all changes from main
git switch main
git merge tmp            # fast-forward to tmp HEAD, which is dev
git branch -D tmp        # deleting tmp

(Edición 2011):

Este flujo de trabajo ha sido informado en esta publicación de blog por el OP :

¿Por qué quiero esto otra vez?

Mientras mi repositorio no tuviera nada que ver con la versión pública, todo estaba bien, pero como ahora quiero poder colaborar en WIP con otros miembros del equipo y contribuyentes externos, quiero asegurarme de que mis ramas públicas estén confiable para que otros se bifurquen y extraigan, es decir, no más rebase y restablecimiento de cosas que he enviado a la copia de seguridad remota, ya que ahora está en GitHub y es pública.

Entonces eso me deja con cómo debo proceder.
El 99% de las veces, mi copia irá al master ascendente, por lo que quiero trabajar con mi master y enviarlo al master la mayor parte del tiempo.
Pero de vez en cuando, lo que tengo wipserá invalidado por lo que va hacia arriba, y abandonaré alguna parte de mi wip.
En ese punto, quiero volver a sincronizar mi maestro con el flujo ascendente, pero no destruir ningún punto de confirmación en mi maestro enviado públicamente. Es decir, quiero una fusión con upstream que termine con el conjunto de cambios que haga que mi copia sea idéntica a upstream .
Y eso es lo que git merge --strategy=theirsdebería hacer.


git merge --strategy=theirsSimulación #2

Se muestra como una fusión, con el nuestro como primer padre.

(propuesto por jcwenger )

git checkout -b tmp upstream
git merge -s ours thebranch         # ignoring all changes from downstream
git checkout downstream
git merge --squash tmp               # apply changes from tmp, but not as merge.
git rev-parse upstream > .git/MERGE_HEAD #record upstream 2nd merge head
git commit -m "rebaselined thebranch from upstream" # make the commit.
git branch -D tmp                    # deleting tmp

git merge --strategy=theirsSimulación #3

Esta publicación de blog menciona :

git merge -s ours ref-to-be-merged
git diff --binary ref-to-be-merged | git apply -R --index
git commit -F .git/COMMIT_EDITMSG --amend

a veces quieres hacer esto, y no porque tengas "basura" en tu historial, sino quizás porque quieres cambiar la línea base para el desarrollo en un repositorio público donde se debe evitar el rebase .


git merge --strategy=theirsSimulación #4

(misma publicación de blog)

Alternativamente, si desea mantener las ramas ascendentes locales con capacidad de avance rápido, un posible compromiso es trabajar con el entendimiento de que para sid/inestable, la rama ascendente se puede restablecer/rebasar de vez en cuando (en función de los eventos que finalmente se eliminan). de su control en el lado del proyecto upstream).
Esto no es gran cosa, y trabajar con esa suposición significa que es fácil mantener la sucursal local ascendente en un estado donde solo se necesitan actualizaciones rápidas.

git branch -m upstream-unstable upstream-unstable-save
git branch upstream-unstable upstream-remote/master
git merge -s ours upstream-unstable
git diff --binary ref-to-be-merged | git apply -R --index --exclude="debian/*"
git commit -F .git/COMMIT_EDITMSG --amend

git merge --strategy=theirsSimulación #5

(propuesto por Barak A. Pearlmutter ):

git checkout MINE
git merge --no-commit -s ours HERS
git rm -rf .
git checkout HERS -- .
git checkout MINE -- debian # or whatever, as appropriate
git gui # edit commit message & click commit button

git merge --strategy=theirsSimulación #6

(propuesto por el mismo Michael Gebetsroither ):

Michael Gebetsroither intervino, afirmando que estaba "haciendo trampa";) y dio otra solución con comandos de plomería de nivel inferior:

(No sería git si no fuera posible con comandos solo de git, todo en git con diff/patch/apply no es una solución real;).

# get the contents of another branch
git read-tree -u --reset <ID>
# selectivly merge subdirectories
# e.g. superseed upstream source with that from another branch
git merge -s ours --no-commit other_upstream
git read-tree --reset -u other_upstream     # or use --prefix=foo/
git checkout HEAD -- debian/
git checkout HEAD -- .gitignore
git commit -m 'superseed upstream source' -a

git merge --strategy=theirsSimulación #7

Los pasos necesarios se pueden describir como:

  1. Reemplace su árbol de trabajo con upstream
  2. Aplicar los cambios al índice.
  3. Agregar aguas arriba como segundo padre
  4. Comprometerse

El comando git read-treesobrescribe el índice con un árbol diferente, logrando el segundo paso , y tiene indicadores para actualizar el árbol de trabajo, logrando el primer paso . Al realizar la confirmación, git usa SHA1 en .git/MERGE_HEAD como segundo padre, por lo que podemos completar esto para crear una confirmación de fusión. Por lo tanto, esto se puede lograr con:

git read-tree -u --reset upstream                 # update files and stage changes
git rev-parse upstream > .git/MERGE_HEAD          # setup merge commit
git commit -m "Merge branch 'upstream' into mine" # commit
VonC avatar Feb 06 '2011 08:02 VonC

Me parece que solo necesitas hacer:

$ git reset --hard origin/master

Si no hay ningún cambio para impulsar hacia arriba y simplemente desea que la rama ascendente sea su rama actual, esto lo hará. No es perjudicial hacer esto localmente , pero perderá cualquier cambio local** que no se haya enviado al maestro.

** En realidad, los cambios aún existen si los ha confirmado localmente, ya que las confirmaciones seguirán estando en su archivo git reflog, generalmente durante al menos 30 días.

wuputah avatar Feb 06 '2011 08:02 wuputah

Puedes hacer esto con bastante facilidad ahora:

$ git fetch origin
$ git merge origin/master -s recursive -Xtheirs

Esto sincroniza su repositorio local con el origen y preserva el historial.

 avatar Nov 16 '2012 04:11