¿Cómo 'sobrescribo', en lugar de 'fusionar', una rama en otra rama en Git?

257

Tengo dos ramas emaily staging. staginges el último y ya no necesito los viejos cambios en la emailrama, pero no quiero eliminarlos.

Así que sólo quiero volcar todo el contenido de staginga emailfin de que ambos apuntan a la misma se comprometen. ¿Es eso posible?

Rafid
fuente
44
Posible duplicado de Cambiar la rama actual a master en git
Tomas Kubes

Respuestas:

196

Puede usar la estrategia de fusión 'nuestra':

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head
knittl
fuente
26
Intenté esto, y me parece al revés? ¿No arroja esto el contenido del correo electrónico a la puesta en escena y no al revés?
Max
27
@Max Tuve la misma confusión y me causó muchos problemas. Debe ejecutar este comando desde la rama más nueva (puesta en escena) y luego hacer una fusión / RP normal a su rama anterior (correo electrónico).
MrGlass
77
¿Por qué ;al final de cada comando? Lo hice sin el ;y parece estar funcionando. Además, esta respuesta está incompleta, el tercer paso es verificar la antigua rama (correo electrónico) y luego fusionarla con la puesta en escena nuevamente.
Rosdi Kasim
44
git rebase -s theirs <oldbranc> <newbranch> funciona bien (no importa en qué rama se encuentre). Tenga en cuenta que en rebase 'suyo' es en realidad la nueva rama porque 'nuestro' es la cabeza a la que estamos aplicando los commits.
Rolf
44
@Rolf: pero rebase eliminará la información de fusión y aplana el historial. No necesariamente lo que buscas. Tampoco es una buena idea, si está trabajando con un historial ya publicado.
knittl
99

Si solo desea que las dos ramas 'correo electrónico' y 'puesta en escena' sean las mismas, puede etiquetar la rama 'correo electrónico', luego restablecer la rama 'correo electrónico' a la 'puesta en escena':

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

También puede cambiar la base de la rama 'provisional' en la rama 'correo electrónico'. Pero el resultado contendrá la modificación de las dos ramas.

Sylvain Defresne
fuente
1
probablemente media git checkout, git checkno existe, que yo sepa
knittl
44
Tienes razón, estoy tan acostumbrado a completar el comando git con pestañas que siempre escribo "git check <TAB>" para escribir "git checkout". Corregido
Sylvain Defresne
17
git reset rompe el repositorio de otras personas que han clonado su repositorio
Geoffrey De Smet
Creo que esta es la respuesta correcta. emailla cabeza de la rama solo debe apuntar a la misma cabeza stagingy ambas tendrán las mismas confirmaciones, el mismo historial.
cicerocamargo
76

He visto varias respuestas y ese es el único procedimiento que me permite solucionarlo sin ningún conflicto.

Si desea todos los cambios de branch_new en branch_old, entonces:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

una vez aplicados esos cuatro comandos, puede presionar el branch_old sin ningún problema

Brugolo
fuente
55
Su respuesta realmente se ajustaba mejor a mi problema, ya que no quería restablecer el HEAD, solo establecía una preferencia por los archivos más nuevos en la rama más nueva al fusionar cosas en la anterior, ¡y funcionó sin problemas! +1
estufas
Empujé mi branch_new a remoto después de la "fusión de los nuestros", y este método funcionó para mí. ¿Era necesario que yo empujara? ¿O habría funcionado sin? (No estaba seguro de si usaría la sucursal local o remota). ¡Gracias!
aspergillusOryzae
¿Por qué no puedes simplemente hacer lo siguiente? git checkout branch_old git merge -s suyo branch_new Pista tomada de stackoverflow.com/questions/14275856/…
Ripu Daman
Dice, no se pudo encontrar la estrategia de fusión 'la suya'.
arango_86
Funciona perfectamente para mí, tiene la ventaja de no resetear nada
Romain
68

Las otras respuestas me dieron las pistas correctas, pero no ayudaron por completo.

Esto es lo que funcionó para mí:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

Sin el cuarto paso de fusionarse con nuestra estrategia, el impulso se considera una actualización que no avanza rápidamente y será rechazado (por GitHub).

Shyam Habarakada
fuente
Eso hace que el mensaje merge-commit sea incorrecto, pero sí, funciona muy bien.
cdunn2001
cdunn2001, tengo curiosidad. ¿Cuál fue el mensaje de confirmación de fusión que esperaba y cómo se confundió con esto?
Shyam Habarakada
Dice "Combinar la rama de seguimiento remoto 'origen / correo electrónico' en el correo electrónico". No menciona la puesta en escena. No es gran cosa sin embargo. Simplemente modifique el commit o use merge -m 'This is not my beautiful house.' -s ours origin/email.
cdunn2001
@ShyamHabarakada, hago lo que usted dice, y me sale el problema de la actualización no rápida. porque no pasa nada cuando hago el cuarto paso.
kommradHomer
El cuarto paso requiere que use el origen / correo electrónico, no funciona solo con el correo electrónico local.
Travis Reeder
45

Si eres como yo y no quieres lidiar con la fusión, puedes hacer los pasos anteriores, excepto usar la fuerza en lugar de la fusión, porque creará un rastro de papel de registro que distrae:

git checkout email
git reset --hard staging
git push origin email --force

Nota: Esto es solo si REALMENTE nunca desea volver a ver las cosas en el correo electrónico.

jsarma
fuente
1
correo electrónico de origen de git push --force no funcionó para mí ya que Step2 dejó ramas divergentes. Entonces, después del Paso 2, esto es lo que hice: git reset origin / email y luego git push
user3505394
2
Esto es exactamente lo que se hizo en cuestión: "cómo sobrescribir en lugar de fusionar". Se debe aceptar la respuesta.
jozols
17

Quería fusionar dos ramas para que todos los contenidos old_branchse actualicen con los contenidos denew_branch

Para mí esto funcionó a las mil maravillas:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch
Madhu
fuente
10

Qué tal si:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease
Arek S
fuente
@emptywalls porque hace un esfuerzo forzado sin advertir al usuario que puede ser rechazado por el servidor, ni explica por qué es necesario. Dicho esto, es una opción viable para un proyecto de un desarrollador
David Costa
@DavidCosta ¿por qué el servidor rechazaría esto? esta es una simple eliminación de la rama de correo electrónico y copiar la puesta en escena en el correo electrónico '... Así que solo quiero volcar todo el contenido de' puesta en escena 'en' correo electrónico 'para que ambos apunten a la misma confirmación', eso es exactamente lo que está sucediendo aquí.
Arek S
@ArekS puede ser rechazado por un enlace del lado del servidor si la rama está configurada como "protegida", por ejemplo, en GitLab. El problema es que si alguien más obtuvo su rama del correo electrónico antes de esta operación y luego intenta presionar, las referencias ya no coinciden (porque algunas confirmaciones simplemente desaparecieron)
David Costa
1
Edité el original de --force a --force-with-lease, que hace el truco de una manera no destructiva.
frandroid
1
Esta es la mejor manera si solo quiere volar una rama e iniciarla limpia desde la rama fuente.
Shane
6

Otras respuestas parecían incompletas.
He intentado a continuación en su totalidad, y funcionó bien.

NOTA:
1. Haga una copia de su repositorio antes de intentar a continuación, para estar seguro.

Detalles:
1. Todo el desarrollo ocurre en la rama de desarrollo
2. La rama de qa es la misma copia del desarrollo
3. De vez en cuando, el código de desarrollo debe moverse / sobrescribirse a la rama de qa

entonces necesitamos sobrescribir una rama qa, desde la rama dev

Parte 1:
con los siguientes comandos, el antiguo qa se ha actualizado a un nuevo desarrollador:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

El comentario automático para el último empuje da a continuación:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

Este comentario parece inverso, porque la secuencia anterior también parece inversa

Parte 2:

A continuación se muestran nuevos compromisos locales inesperados en desarrollo, los innecesarios,
por lo que debemos descartarlos y hacer que los desarrolladores no se vean afectados.

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

Parte 3:
Verifique que todo esté como se esperaba:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

Eso es todo.
1. el qa antiguo ahora se sobrescribe con el nuevo código de sucursal del desarrollador
2. local está limpio (el origen / dev remoto no se ha modificado)

Manohar Reddy Poreddy
fuente
6

La forma más fácil de hacerlo:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

Ahora la rama de correo electrónico y la puesta en escena son las mismas.

B.Neo
fuente
2
Advertencia: Esto elimina todas las confirmaciones en la emailrama. Es como eliminar la emailrama y crearla de nuevo en la cabecera de la stagingrama.
Cameron Hudson
2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging
Willa
fuente
1
Esta respuesta habría sido más clara para mí si el comentario se hubiera separado del comentario de fusión en el comando. Explique brevemente qué hace -X y cómo afecta a esta fusión. Gracias sin embargo. Me hizo buscarlo :)
noelicus
@noelicus gracias por el comentario y tienes razón. Podría editar la respuesta en el futuro.
Willa
0

Este no altera la rama más nueva original, y le da la oportunidad de realizar más modificaciones antes de la confirmación final.

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
Jan Kyu Peblik
fuente