¿Cómo puedo enviar una confirmación específica a una confirmación remota y no confirmaciones anteriores?

Respuestas:

1087

Para avanzar a través de una confirmación dada, puede escribir:

git push <remotename> <commit SHA>:<remotebranchname>

siempre <remotebranchname>existe en el control remoto. (Si no es así, puede usarlo git push <remotename> <commit SHA>:refs/heads/<remotebranchname>para crearlo automáticamente).

Si desea impulsar una confirmación sin presionar las confirmaciones anteriores, primero debe usar git rebase -ipara reordenar las confirmaciones.

Geoff Reedy
fuente
66
git push <remotename> <commit SHA>:<remotebranchname>trabajos. el truco es combinarlo git rebase -ipara mover el commit que desea como primer commit y especificar ese commit-sha
dminer el
29
Otro consejo es buena para asegurarse de copiar el SHA de la confirmación tiene usted quiere empujar después haciendo que rebase -i, y no antes, como yo acabo de hacer :)
estan
33
Tenga en cuenta que esto falla si la rama remota aún no existe. La creación de la rama se puede hacer con git push <remotename> <commit SHA>:refs/heads/<new remote branch name>. Después de esto, presione como lo describe la respuesta.
Wes Oldenbeuving
32
Por ejemplo, para empujar todo menos el último commit con algunos nombres estándar git push origin HEAD~1:master.
ruido sin arte
3
También tenga en cuenta que si ya ha empujado un SHA posterior a esa rama remota, tendrá que forzarlo. Usa la -fbandera.
Ian Vaughan
79

Las otras respuestas faltan en las descripciones de reordenamiento.

git push <remotename> <commit SHA>:<remotebranchname>

empujará una única confirmación, pero esa confirmación debe ser la MÁS ANTIGUA de sus confirmaciones locales, no enviadas, no debe confundirse con la confirmación superior, la primera o la sugerencia, que en mi opinión son descripciones ambiguas. El commit necesita el más antiguo de sus commits, es decir, el más alejado de su commit más reciente. Si no es la confirmación más antigua, se enviarán todas las confirmaciones de su SHA local, no empujado más antiguo al SHA especificado. Para reordenar las confirmaciones use:

git rebase -i HEAD~xxx

Después de reordenar el commit, puede enviarlo de manera segura al repositorio remoto.

Para resumir, solía

git rebase -i HEAD~<number of commits to SHA>
git push origin <post-rebase SHA>:master

para enviar un solo commit a mi rama maestra remota.

Referencias

  1. http://blog.dennisrobinson.name/push-only-one-commit-with-git/
  2. http://blog.dennisrobinson.name/reorder-commits-with-git/

Ver también:

  1. git: confirmaciones duplicadas después de una rebase local seguida de extracción
  2. git: Empujar confirmaciones individuales, reordenar con rebase, confirmaciones duplicadas
Samuel
fuente
3
Parece que algunos orígenes no permiten esto. Por ejemplo, con GitLab veo "No está permitido forzar el código de inserción a una rama protegida en este proyecto". Lo cual es un poco extraño ya que no pensé que estaba forzando nada, solo haciendo un empujón normal. ¿Alguna idea de cómo hacerlo sin 'forzar'?
Ed Avis
1
@Ed Shoud no habrá necesidad de forzar el empuje Parece que tienes un problema con tu configuración específica de git. ¿Quizás rebasaste el mando HEAD remoto? No sé qué es una rama protegida, parece un problema de permiso.
Samuel
1
Samuel, eso tendría sentido, pero git rebase -i solo te muestra los commits locales que son posteriores al HEAD remoto, así que no sé cómo podría haberlo hecho.
Ed Avis el
1
Samuel: de hecho, puedo hacer empujes parciales ahora, así que no sé qué salió mal, pero debe haber estado tratando de empujar un commit no derivado de HEAD remoto de una manera u otra.
Ed Avis
1
@Ed Dijiste "git rebase -i solo te muestra los commits locales que son posteriores al HEAD remoto", no creo que esto sea cierto. Probé y pude rebasar el HEAD remoto.
Samuel
25

Sugeriría usar git rebase -i; mueve la confirmación que deseas impulsar a la parte superior de las confirmaciones que has realizado. Luego, use git logpara obtener el SHA de la confirmación modificada, compruébelo y empújelo. El rebase asegurará que todos tus otros commits sean ahora hijos del que presionaste, por lo que los empujes futuros también funcionarán bien.

Walter Mundt
fuente
3
¿Podría quizás dar un movimiento completo ejemplo esp. re el git logpaso?
Drux
44
Digamos que tiene 3 confirmaciones relativamente independientes con los mensajes "A", "B", "C" confirmados en ese orden y desea presionar "B". 'git rebase -i' debería hacer que usted y el editor enumeren los tres; mueva B hacia arriba y guarde / salga. 'git log --pretty = oneline -n3' listará B, A, C con hashes antes de cada mensaje, con B ahora al final. 'git checkout -b temp $ hash_of_B; git push 'debería empujar a B en ese punto. Entonces probablemente querrás 'git checkout -b master; git branch -d temp 'para volver a su estado anterior, suponiendo que estuviera en su rama maestra local; reemplazar según corresponda.
Walter Mundt
1
+1 ¿Alguna vez te encontraste con la "ira de los dioses git" después de rebase-push-rebase? (Podría suceder también por accidente, ¿verdad?)
Drux
2
Si lee mi respuesta detenidamente, verá que la inserción solo ocurre después de la modificación, y la confirmación modificada solo se mueve por encima de otras confirmaciones que aún no se han enviado. Una vez que se empuja un commit, generalmente se debe considerar establecido en piedra; déjalo solo en futuros rebases. Esta técnica es solo para que pueda ordenar múltiples cambios locales en un buen orden antes de empujarlos. Si tiene el seguimiento configurado correctamente, 'git rebase -i' sin ningún otro argumento por defecto ni siquiera mostrará las confirmaciones empujadas, por lo que es más seguro contra accidentes que algunos otros métodos.
Walter Mundt
21

Cherry-pick funciona mejor en comparación con todos los demás métodos, mientras que empuja una confirmación específica.

La forma de hacerlo es:

Crea una nueva sucursal -

git branch <new-branch>

Actualice su nueva sucursal con su sucursal de origen:

git fetch

git rebase

Estas acciones asegurarán que tengas exactamente las mismas cosas que tu origen.

Elige el sha idque quieres hacer.

git cherry-pick <sha id of the commit>

Puedes obtenerlo sha idcorriendo

git log

Empújalo a tu origen

git push

Corre gitkpara ver que todo se ve de la misma manera que querías.

David
fuente
2
El uso git rebase -iserá la solución ideal como se sugiere en las soluciones anteriores. La selección de cereza debe usarse solo cuando desee duplicar la confirmación.
Vinay Bhargav
13

Creo que tendrías que "volver atrás" a ese compromiso y luego empujarlo. O podría cherry-pickcomprometerse en una nueva rama y enviarla a la rama en el repositorio remoto. Algo como:

git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin {branch}
Josh K
fuente
99
git revert es una mala idea aquí - crea un nuevo commit
hasen
1
@hasen: Podrías simplemente hacer cherry-pickel commit que quieras.
Josh K
44
tanto revertir como elegir cerezas son malas ideas. git rebase -i es tu amigo aquí, mira la respuesta de Walter Mundt a continuación.
Nicolas C
3
@Nicolas, ¿por qué Cherry-Pick es una mala idea?
Antoine
3
@Antoine, normalmente desea que su rama permanezca sincronizada con la que rastrea en origen. Si elige con precisión, está haciendo una copia / pegado, y tendrá que lidiar con la copia no empujada en algún momento. Si rebase -i, "corta y pega", y mantiene su rama sincronizada con el control remoto hasta donde desea que esté.
Nicolas C
0

También podría, en otro directorio:

  • git clone [tu repositorio]
  • Sobrescriba el directorio .git en su repositorio original con el directorio .git del repositorio que acaba de clonar en este momento.
  • git add y git confirman tu original
NunoSempere
fuente