tag remota rama partir otra crear comandos cambiar git github branching-and-merging

remota - git push



git comando para hacer una rama como otra (7)

Intento tomar una rama con cambios y traerla de vuelta para que sea idéntica a la corriente ascendente desde la que divergió. Los cambios son locales y se han enviado a github, por lo que ni git reset ni git rebase son realmente viables, ya que cambian el historial, lo cual es malo con una rama que ya se ha enviado.

También probé la git merge con varias estrategias, pero ninguna de ellas deshace los cambios locales, es decir, si agregué un archivo, una fusión podría hacer que otros archivos vuelvan a estar en línea, pero aún tendré ese archivo que el anterior no no tiene.

Podría simplemente crear una nueva rama desde el inicio, pero realmente me gustaría una fusión que en términos de historial de revisión aplique todos los cambios para tomar mi rama y hacerla idéntica a la anterior, de modo que pueda impulsar ese cambio de forma segura sin historia de traición ¿Hay tal comando o serie de comandos?


Me parece que solo necesitas hacer:

$ git reset --hard origin/master

Si no hay ningún cambio para impulsar en sentido ascendente, y usted simplemente quiere que la rama ascendente sea su rama actual, esto hará eso. No es dañino hacer esto localmente, pero perderá cualquier cambio local ** que no haya sido empujado a dominar.

** En realidad, los cambios siguen vigentes si los ha confirmado localmente, ya que las confirmaciones aún se guardarán en su git reflog , generalmente durante al menos 30 días.


Otra simulación para git merge -s theirs ref-to-be-merged :

git merge --no-ff -s ours ref-to-be-merged # enforce a merge commit; content is still wrong git reset --hard HEAD^2; git reset --soft HEAD@{1} # fix the content git commit --amend

Una alternativa al doble reinicio sería aplicar el parche inverso:

git diff --binary ref-to-be-merged | git apply -R --index


Pesado, pero qué demonios, ¿qué puede salir mal?

  • Mira la rama X que quieres que se parezca a la Y
  • cp -r .git / tmp
  • Mira la rama Y
  • rm -rf .git && cp -r /tmp/.git.
  • Comprometerse y empujar cualquier diferencia
  • HECHO.

Podría fusionar su rama ascendente con su rama de desarrollo, con un controlador de combinación personalizado "keepTheirs" :
Ver "se necesita" git merge -s theirs "- pero sé que no existe ".
En su caso, solo se requerirá un keepTheirs y un script keepTheirs como:

mv -f $3 $2 exit 0

git merge --strategy=theirs Simulation # 1

Se muestra como una combinación, con el flujo ascendente como primer padre.

Jefromi menciona (en los comentarios) la merge -s ours , al fusionar su trabajo en el Jefromi ascendente (o en una rama temporal comenzando desde el origen), y luego reenviar rápidamente su rama al resultado de esa combinació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 el beneficio de registrar el antecesor en sentido ascendente como primer padre, de modo que la fusión significa "absorber esta rama de tema desactualizada" en lugar de "destruir esta rama de tema y reemplazarla por la de flujo ascendente" .

(Editar 2011):

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

¿Por qué quiero esto de nuevo?

Siempre y cuando mi repositorio no tuviera nada que ver con la versión pública, todo estaba bien, pero como ahora quisiera tener la posibilidad de coloidal en WIP con otros miembros del equipo y colaboradores externos, quiero asegurarme de que mis sucursales públicas sean confiable para que otros se ramifiquen y se desconecten, es decir, que no haya más bases de datos reestablecidas y restablecer en cosas que he transferido a la copia de seguridad remota, ya que ahora está en GitHub y en público.

Entonces eso me deja con cómo debo proceder.
El 99% del tiempo, mi copia irá al maestro de nivel superior, por lo que quiero trabajar con mi maestro y avanzar en la fase ascendente la mayor parte del tiempo.
Pero de vez en cuando, lo que tengo en wip quedará invalidado por lo que entra aguas arriba y abandonaré una parte de mi wip .
En ese punto, quiero volver a sincronizar a mi maestro con el flujo ascendente, pero no destruir ningún punto de compromiso en mi maestro enviado públicamente. Es decir, quiero una fusión con upstream que termine con el conjunto de cambios que hace que mi copia sea idéntica a la anterior .
Y eso es lo que se git merge --strategy=theirs debería hacer.

git merge --strategy=theirs Simulation # 2

Se muestra como una combinación, con el nuestro como el 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=theirs Simulation # 3

Esta entrada del 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 desea hacer esto, y no porque tenga "basura" en su historial, sino quizás porque desea cambiar la línea de base para el desarrollo en un repositorio público donde debe evitarse el rebase .

git merge --strategy=theirs Simulation # 4

(misma publicación en el blog)

Alternativamente, si desea mantener las ramas ascendentes locales rápidamente reenviables, un posible compromiso es trabajar con la comprensión de que para sid / inestable, la rama ascendente puede restablecerse o reajustarse ocasionalmente (en función de los eventos que finalmente están fuera de servicio). de su control en el lado del proyecto aguas arriba).
Esto no es un gran problema y trabajar con esa suposición significa que es fácil mantener la sucursal upstream local 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=theirs Simulation # 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=theirs Simulation # 6

(propuesto por el mismo Michael Gebetsroither ):

Michael Gebetsroither intervino, alegando que estaba "engañando";) y dio otra solución con los comandos de plomería de bajo nivel:

(No sería genial si no fuera posible con comandos de git only, 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


Puedes hacer esto bastante fácilmente ahora:

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

Esto hace que su repositorio local esté sincronizado con el origen y preserva el historial.


También hay una manera con poca ayuda del comando de fontanería: en mi humilde opinión, la más directa. Digamos que quiere emular "theirs" para el caso de 2 ramas:

head1=$(git show --pretty=format:"%H" -s foo) head2=$(git show --pretty=format:"%H" -s bar) tree=$(git show --pretty=format:"%T" -s bar) newhead=$(git commit-tree $tree -p $head1 -p $head2 <<<"merge commit message") git reset --hard $newhead

Esto combina un número arbitrario de cabezales (2 en el ejemplo anterior) utilizando el árbol de uno de ellos (barra en el ejemplo anterior, proporcionando el árbol ''theirs''), sin tener en cuenta los problemas de diff / file (commit-tree es un comando de bajo nivel, por lo que no se preocupa por eso). Tenga en cuenta que head puede ser solo 1 (tan equivalente a cherry-pick con "theirs").

Tenga en cuenta que la cabeza padre que se especifica primero, puede influir en algunas cosas (véase, por ejemplo, el primer padre del comando git-log), así que tenlo en cuenta.

En lugar de git-show, se puede usar cualquier otra cosa capaz de generar hash de compilación y de compilación, cualquiera que sea el que se use para analizar (cat-file, rev-list, ...). Puede seguir todo con el compromiso de git --mendar para embellecer interactivamente el mensaje de compromiso.


cambiar a la rama ascendente remota y hacer una git merge con la estrategia de combinación establecida en la ours .

git checkout origin/master git merge dev --strategy=ours git commit ... git push

Toda la historia seguirá estando presente, pero tendrás una fusión adicional. Lo importante aquí es comenzar desde la versión en la que quieres estar y fusionar la ours con la rama en la que github se encuentra actualmente.