Forzar "git push" para sobrescribir archivos remotos

768

Quiero insertar mis archivos locales y tenerlos en un repositorio remoto, sin tener que lidiar con conflictos de fusión. Solo quiero que mi versión local tenga prioridad sobre la remota.

¿Cómo puedo hacer esto con Git?

opensas
fuente
106
¿No git push origin --forcete funcionó?
No está claro si solo desea anular los archivos .git o la copia de trabajo asociada. Si es el repositorio de git, git push es la respuesta. Si desea actualizar la copia de trabajo remota, debe usar un gancho posterior a la recepción
Pierre-Olivier Vares
@ Mike que me funciona por alguna razón ... es de extrañar lo que estaba pasando con el OP
Una causa probable, el empuje forzado no funciona, es que puede haberse desactivado explícitamente en el repositorio remoto (para garantizar que nada se pierda debido a contribuyentes idiotas y / o malignos): utilícelo config receive.denyNonFastforwardspara averiguarlo.
Frank Nocke

Respuestas:

1088

Debería poder forzar su revisión local al repositorio remoto utilizando

git push -f <remote> <branch>

(por ejemplo git push -f origin master) Dejando <remote>y <branch>forzará empujar todas las ramas locales que se han establecido --set-upstream.

Solo tenga en cuenta que si otras personas comparten este repositorio, su historial de revisiones entrará en conflicto con el nuevo. Y si tienen compromisos locales después del punto de cambio, serán invalidados.

Actualización : pensé que agregaría una nota al margen. Si está creando cambios que otros revisarán, entonces no es raro crear una rama con esos cambios y volver a redactar periódicamente para mantenerlos actualizados con la rama de desarrollo principal. Simplemente informe a otros desarrolladores que esto sucederá periódicamente para que sepan qué esperar.

Actualización 2 : debido al creciente número de espectadores, me gustaría agregar información adicional sobre qué hacer cuando upstreamexperimentas un impulso forzado.

Digamos que he clonado su repositorio y he agregado algunas confirmaciones como esta:

            D ---- E tema
           / /
A ---- B ---- C desarrollo

Pero más tarde, la developmentrama se golpea con un rebase, lo que hará que reciba un error así cuando ejecuto git pull:

Desembalaje de objetos: 100% (3/3), hecho.
De <repo-location>
 * desarrollo de sucursal -> FETCH_HEAD
Auto-fusión <archivos>
CONFLICTO (contenido): fusionar conflicto en <ubicaciones>
La fusión automática falló; arregle conflictos y luego confirme el resultado.

Aquí podría solucionar los conflictos y commit, pero eso me dejaría con un historial de cometer realmente feo:

       C ---- D ---- E ---- F tema
      / /
A ---- B -------------- C 'desarrollo

Puede parecer atractivo de usar, git pull --forcepero ten cuidado porque eso te dejará con compromisos varados:

            D ---- E tema

A ---- B ---- C 'desarrollo

Entonces, probablemente la mejor opción es hacer un git pull --rebase. Esto requerirá que resuelva cualquier conflicto como antes, pero para cada paso en lugar de comprometerlo lo usaré git rebase --continue. Al final, el historial de confirmación se verá mucho mejor:

            D '--- E' tema
           / /
A ---- B ---- C 'desarrollo

Actualización 3: También puede usar la --force-with-leaseopción como un impulso de fuerza "más seguro", como lo menciona Cupcake en su respuesta :

El empuje forzado con un "arrendamiento" permite que el empuje forzado falle si hay nuevas confirmaciones en el control remoto que no esperaba (técnicamente, si aún no las ha traído a su rama de seguimiento remoto), lo cual es útil si no desea sobrescribir accidentalmente los compromisos de otra persona que aún no conocía, y solo desea sobrescribir los suyos:

git push <remote> <branch> --force-with-lease

Puede obtener más detalles sobre cómo usar --force-with-leaseleyendo cualquiera de los siguientes:

Trevor Norris
fuente
55
Como esta es la respuesta seleccionada, comentaré aquí. Usar la fuerza no es un problema cuando trabajas solo. Por ejemplo, mi host en la nube comienza con su propio git. Si trabajo localmente y construyo un proyecto, y quiero ponerlo en mi host en la nube (OpenShift), tengo dos proyectos git separados. Mi local y mi OpenShift uno. Recibo mi local tal como me gusta, pero ahora quiero obtener una vista previa en mi OpenShift. Luego empujas a OpenShift por primera vez, usando la -fbandera. Básicamente, coloca tu git local en OpenShift.
Wade
128

Quieres forzar empujar

Lo que básicamente quieres hacer es forzar el empuje de tu rama local para sobrescribir la remota.

Si desea una explicación más detallada de cada uno de los siguientes comandos, consulte mi sección de detalles a continuación. Básicamente tiene 4 opciones diferentes para forzar el empuje con Git:

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

Si desea una explicación más detallada de cada comando, consulte mi sección de respuestas largas a continuación.

Advertencia: el empuje forzado sobrescribirá la rama remota con el estado de la rama que está presionando. Asegúrese de que esto es lo que realmente quiere hacer antes de usarlo, de lo contrario, puede sobrescribir las confirmaciones que realmente desea mantener.

Forzar detalles de empuje

Especificar el control remoto y la rama

Puede especificar completamente ramas específicas y un control remoto. La -fbandera es la versión corta de--force

git push <remote> <branch> --force
git push <remote> <branch> -f

Omitiendo la rama

Cuando se omite la bifurcación a la bifurcación, Git la resolverá según la configuración de configuración. En las versiones de Git posteriores a 2.0, un nuevo repositorio tendrá una configuración predeterminada para impulsar la rama actualmente desprotegida:

git push <remote> --force

mientras que antes de 2.0, los nuevos repositorios tendrían configuraciones predeterminadas para impulsar múltiples sucursales locales. Las configuraciones en cuestión son las configuraciones remote.<remote>.pushy push.default(ver más abajo).

Omitiendo el control remoto y la rama

Cuando se omiten tanto el control remoto como la rama, el comportamiento de solo git push --forceestá determinado por la push.defaultconfiguración de configuración de Git:

git push --force
  • A partir de Git 2.0, la configuración predeterminada, simplebásicamente empujará su rama actual a su contraparte remota ascendente. El control remoto está determinado por la branch.<remote>.remoteconfiguración de la sucursal y, de lo contrario, el repositorio de origen es el predeterminado.

  • Antes de Git versión 2.0, la configuración predeterminada matching, básicamente, empuja todas sus sucursales locales a sucursales con el mismo nombre en el control remoto (que por defecto es el origen).

Puede leer más push.defaultconfiguraciones leyendo git help configo una versión en línea de la página de manual de git-config (1) .

Fuerza a empujar de manera más segura con --force-with-lease

El empuje forzado con un "arrendamiento" permite que el empuje forzado falle si hay nuevas confirmaciones en el control remoto que no esperaba (técnicamente, si aún no las ha traído a su rama de seguimiento remoto), lo cual es útil si no desea sobrescribir accidentalmente los compromisos de otra persona que aún no conocía, y solo desea sobrescribir los suyos:

git push <remote> <branch> --force-with-lease

Puede obtener más detalles sobre cómo usar --force-with-leaseleyendo cualquiera de los siguientes:

Comunidad
fuente
Tienes razón, pero esto solo debería usarse en situaciones excepcionales .
Scott Berrevoets
1
@ScottBerrevoets " Preferiría presionar lo que tengo y dejar que se sobrescriba de forma remota en lugar de integrarse " . Le di al OP exactamente lo que me pidió.
Lo sé, pero OP puede no ser consciente de las consecuencias de hacer esto. Técnicamente respondiste la pregunta, pero creo que una advertencia para no hacer esto no está fuera de lugar.
Scott Berrevoets
1
@ScottBerrevoets Estoy tratando de que un moderador combine mi respuesta en el canónico, porque menciono la nueva --force-with-leaseopción;)
1
FYI: se fusionó de stackoverflow.com/questions/24768330/…
Shog9
32

Otra opción (para evitar cualquier empuje forzado que pueda ser problemático para otros contribuyentes) es:

  • ponga sus nuevos commits en una rama dedicada
  • restablecer masterelorigin/master
  • combine su rama dedicada master, manteniendo siempre los compromisos de la rama dedicada (lo que significa crear nuevas revisiones además de las mastercuales reflejarán su rama dedicada).
    Ver " comando git para hacer una rama como otra " para estrategias para simular a git merge --strategy=theirs.

De esa manera, puede empujar el maestro al control remoto sin tener que forzar nada.

VonC
fuente
¿Cómo difiere el resultado de "push -force"?
alexkovelsky
66
@alexkovelsky Cualquier impulso forzado reescribiría el historial, lo que obligaría a otros usuarios del repositorio a restablecer su propio repositorio local para que coincida con las confirmaciones recientemente enviadas. Este enfoque solo crea nuevas confirmaciones y no requiere un impulso forzado.
VonC
1
Sugiero que agregue un encabezado a su respuesta: "No desea forzar el empuje" :)
alexkovelsky
@alexkovelsky Buen punto. He editado la respuesta en consecuencia.
VonC
4

git push -f es un poco destructivo porque restablece cualquier cambio remoto que haya realizado cualquier otra persona en el equipo. Una opción más segura es {git push --force-with-lease}.

Lo que hace {--force-with-lease} es negarse a actualizar una sucursal a menos que sea el estado que esperamos; es decir, nadie ha actualizado la rama aguas arriba. En la práctica, esto funciona comprobando que la referencia ascendente es lo que esperamos, porque las referencias son hashes y codifican implícitamente la cadena de padres en su valor. Puede decirle a {--force-with-lease} exactamente qué verificar, pero de forma predeterminada verificará la referencia remota actual. Lo que esto significa en la práctica es que cuando Alice actualiza su rama y la empuja hacia el repositorio remoto, el cabezal de referencia de la rama se actualizará. Ahora, a menos que Bob haga una extracción desde el control remoto, su referencia local al control remoto estará desactualizada. Cuando va a empujar usando {--force-with-lease}, git verificará la referencia local contra el nuevo control remoto y se negará a forzar el empuje. {--force-with-lease} efectivamente solo le permite forzar-empujar si nadie más ha empujado los cambios al control remoto mientras tanto. Es {--force} con el cinturón de seguridad puesto.

Lando Ke
fuente
3

Funciona para mi:

git push --set-upstream origin master -f
Jithish PN
fuente
0

Pasos simples usando tortoisegit

GIT asigna archivos locales y se compromete con el repositorio de git.

Pasos:

1) el alijo cambia el nombre del alijo

2) tirar

3) stash pop

4) confirme 1 o más archivos y proporcione la descripción de los cambios de confirmación del autor del conjunto y la fecha

5) empujar

Nagnath Mungade
fuente