Dado que la ramificación es barata con Git, ¿por qué no pagar una copia y luego no necesita hacer una ejecución en seco? Puedes tirar la copia después.
Esto es genial, pero aún modificará su copia de trabajo. Si tu repositorio es un servidor web en vivo, entonces usted podría estar sirviendo archivos con conflictos en.
dave1010
21
Realmente no puede hacer una fusión sin afectar la copia de trabajo.
mipadi
55
Es cierto, pero algo como git merge --only-if-there-wont-be-any-conflictso git diff --show-conflicts <commit>sería realmente útil. Es una pena que todavía no sea posible, o me estoy perdiendo algo
dave1010
344
@ dave1010 ¡Nunca deberías manejar fusiones en un servidor web en vivo! ¡Para eso está tu caja de desarrollo! Arregle la rama "prod" y luego empújela al servidor web real.
jpswain
52
Si trabaja en un servidor en vivo / producción, ¡nunca querrá hacer otra cosa que no sea git pull --ff-only!
ThiefMaster
237
Simplemente tuve que implementar un método que encuentra automáticamente conflictos entre un repositorio y su control remoto. Esta solución se fusiona en la memoria para que no toque el índice ni el árbol de trabajo. Creo que esta es la forma más segura posible de resolver este problema. Así es como funciona:
Obtenga el control remoto en su repositorio. Por ejemplo:
git fetch origin master
Ejecute git merge-tree: git merge-tree mergebase master FETCH_HEAD( mergebase es la identificación hexadecimal que merge-base imprimió en el paso anterior)
Ahora suponga que desea fusionar el maestro remoto con su maestro local, pero puede usar cualquier rama. git merge-treeejecutará la fusión en la memoria e imprimirá el resultado en la salida estándar. Grep para el patrón <<o >>. O puede imprimir el resultado en un archivo y verificarlo. Si encuentra una línea que comienza con 'cambiado en ambos', lo más probable es que haya un conflicto.
Esta respuesta está subestimada, en mi humilde opinión, ya que es una solución limpia sin tocar la copia de trabajo o el índice.
sschuberth
23
Por cierto, los pasos 2 y 3 se pueden combinar en un solo paso, utilizando el operador de backtick de la consola de Linux, que evalúa en su lugar su contenido:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g
15
Agregue a [alias] en .gitconfig: dry = "! F () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "# verifique cómo irá la fusión de dev en master: git dry maestro de desarrollo
Noel
8
Mi nueva línea GIT favorita: ¡ git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"simplemente increíble! +100
Rudie
44
Al probar esto, encontré grepping para combinaciones de banderas 'cambiadas en ambas' donde ambas ramas modifican el mismo archivo, incluso si no dan lugar a un conflicto de fusión. Para identificar solo conflictos reales, me pareció necesario buscar grep para el marcado de conflicto que comienza así: +<<<<<<< .ourpor lo tanto, uso una expresión grep comogrep -q '^+<* \.our$'
Guy
55
Mi solución simple de fuerza bruta para esto es:
Crear una rama "pre-master" (del maestro, por supuesto)
Combina todas las cosas que quieras en este pre-master.
Entonces puedes ver cómo ocurrió la fusión sin tocar al maestro.
Fusionar pre-master en master O
Fusiona todas las ramas liberadas de wannabe en master
De todos modos, seguiría el consejo de @ orange80.
Me gusta la solución @akostajti, pero esta es otra opción subestimada. De hecho, prefiero estar a la defensiva y crear una nueva rama temporal (por supuesto, solo cuando espero conflictos, de lo contrario será una exageración), y si algo sale mal, simplemente elimínelo.
jakub.g
1
No sé si esta es una solución "sucia" o no, pero realmente hace el trabajo. ¡Me gusta! (Y)
Sara
3
Esta debería ser la solución aceptada, imo. Es rápido, fácil, seguro, reversible, intuitivo, y mientras no haya cambios no comprometidos antes de comenzar, no tendrá efectos secundarios.
Bob Ray
3
Esta solución te dice que no entiendes cómo funciona git. Las ramas son solo punteros y solo está creando un puntero redundante. Tiene el mal presentimiento de que de alguna manera puede dañar la fusión de su rama, pero no puede. Siempre puede hacerlo git merge --abortsi hay conflictos, git reset --hard HEAD~1si hubo una fusión o git reset --hard origin/master. Crear otra rama te da una sensación de seguridad, pero si aprendes cómo funciona git, entenderás que es un miedo fuera de lugar. Cuando la preocupación es por no cambiar la copia de trabajo, esto no ofrece solución.
Thibault D.
@ thibault-d Piensa en lo compleja que es la solución cuando no comienzas con una rama limpia. git merge --no-commitno abortará una fusión si se puede reenviar rápidamente. git merge --abortno funciona si se fusionó. Si desea escribir esto como un script, es incómodo, ya git mergeque no responde con códigos de error lo suficientemente buenos como para explicar los diferentes tipos de conflictos. Trabajar con una rama nueva evita que un script roto deje su repositorio en un estado que requiera intervención manual. Claro que no puedes perder nada. Pero es más fácil construir de otra manera.
Erik Aronesty
47
Deshacer una fusión con git es tan fácil que ni siquiera debería preocuparse por la ejecución en seco:
$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world
EDITAR: Como se señala en los comentarios a continuación, si tiene cambios en su directorio de trabajo o área de preparación, probablemente desee guardarlos antes de hacer lo anterior (de lo contrario, desaparecerán después de lo git resetanterior)
Simplemente verificar si una fusión será un avance rápido (FF) es una cuestión de verificar la lista git branch --contains HEADo incluso más directamente, solo usegit merge --ff-only
Brian Phillips el
77
git reset --hard es uno de los pocos comandos de eliminación de información sin retroceso que tiene git, por lo que debe usarse con extrema precaución. Como tal, -1
Kzqai
8
@Tchalvak todavía hay reflog.
Kissaki
3
--dry-runno "simplemente comprobaría si una fusión se adelantará". Devolvería el resultado exacto que haría una fusión: archivos, conflictos, etc. Si will ff no es realmente interesante, ¿verdad?
Rudie
3
¿qué tal git stash; git reset --hard? @BrianPhillips
Code Whisperer
41
Hice un alias para hacer esto y funciona de maravilla, hago esto:
Idea interesante. ¿Cómo vería ese resultado y determinaría si la fusión funcionará o no?
MatrixFrog
66
Esto no le dirá si ocurrirán conflictos ... pero le dará una idea general de lo que sucederá si hiciera una extracción / fusión.
Timh
10
Esto solo le dirá la diferencia entre las dos ramas, no le dirá cuál será el resultado de la fusión. Esta es una distinción importante ya que la fusión en algunos casos tomará automáticamente los cambios de diferentes ramas dependiendo de cuándo se comprometieron. Entonces, en esencia, hacer una diferencia podría hacerte pensar que algunos de tus cambios se revertirán cuando, en realidad, el proceso de fusión tomará automáticamente cambios más nuevos que los anteriores. Espero que tenga sentido.
markquezada
3
Para construir sobre el comentario de @ mirthlab, habrá una diferencia significativa entre diff y merge si alguien realizó previamente una fusión con la estrategia de fusión "nuestra" (o alguna otra reparación manual de fusión); el diff también le mostrará las diferencias que ya se cuentan como "fusionadas".
Tao
21
Yo uso el comando request-pull git para hacerlo. Le permite ver cada cambio que sucedería al fusionar, pero sin hacer nada en sus repositorios locales o remotos .
Por ejemplo, imagine que desea fusionar una rama llamada "feature-x" en su rama maestra
git request-pull master origin feature-x
le mostrará un resumen de lo que sucedería (sin hacer nada):
The following changes since commit fc01dde318:
Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
Adding some layout
Refactoring
ioserver.js | 8 +++---
package.json | 7 +++++-
server.js | 4 +--
layout/ldkdsd.js | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js
Si agrega el -pparámetro, también obtendrá el texto completo del parche, exactamente como si estuviera haciendo un git diff en cada archivo modificado.
Podría aclarar esto un poco agregando qué mastery originhacer en las opciones de línea de comandos, y ¿qué pasa si estoy, por ejemplo, en un local branch1y quiero hacer un request-pullen una rama de característica local branch2? ¿Aún lo necesito origin? Por supuesto, uno siempre puede leer la documentación.
Ela782
Lamentablemente, este comando solo funciona si Rev # 2 es un nombre de rama, no funciona para los hashes: /
Jared Grubb
20
Me sorprende que nadie haya sugerido usar parches todavía.
Digamos que usted desea probar una combinación de your_brancha master(estoy suponiendo que haya mastercomprobado):
error: patch failed: test.txt:1
error: test.txt: patch does not apply
eso significa que el parche no tuvo éxito y una fusión produciría conflictos. Sin salida significa que el parche está limpio y podrá fusionar fácilmente la rama
Tenga en cuenta que esto realmente no cambiará su árbol de trabajo (aparte de crear el archivo de parche, por supuesto, pero puede eliminarlo de forma segura después). De la documentación de git-apply:
--check
Instead of applying the patch, see if the patch is applicable to the
current working tree and/or the index file and detects errors. Turns
off "apply".
Nota para cualquiera que sea más inteligente / más experimentado con git que yo: avíseme si me equivoco aquí y este método muestra un comportamiento diferente al de una fusión regular. Parece extraño que en los más de 8 años que ha existido esta pregunta nadie sugiera esta solución aparentemente obvia.
Este método es la respuesta aceptada para esta pregunta y hay algunas advertencias en los comentarios como "git no pudo usar la estrategia de fusión 'recursiva'" y "el archivo de parche da error para los archivos nuevos". De lo contrario, parece genial.
neno
1
Un camino más corto sin crear un archivo de parche temporal: git diff master your_branch | git apply --check.
ks1322
9
Esto puede ser interesante: de la documentación:
Si intentó una fusión que resultó en conflictos complejos y desea comenzar de nuevo, puede recuperarse con git merge --abort .
Pero también puedes hacerlo de la manera ingenua (pero lenta):
rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)
(Nota: no funcionará simplemente clonando a / tmp, necesitará una copia para asegurarse de que los cambios no confirmados no entren en conflicto).
Copia limpia se puede obtener con cp -r repository/.git /tmp/repository/.git, cd /tmp/repository, git reset --hard, git add --all, git reset --hard(por si acaso), git status(para comprobar que está limpio).
ADTC
8
Soy consciente de que esta es una pregunta antigua, pero es la primera en aparecer en una búsqueda de Google.
Negarse a fusionar y salir con un estado distinto de cero a menos que el HEAD actual ya esté actualizado o la fusión se pueda resolver como un avance rápido.
Hacer esto intentará fusionarse y avanzar rápidamente, y si no puede, aborta y le indica que no se pudo realizar el avance rápido, pero deja intacta su rama de trabajo. Si puede avanzar rápidamente, realizará la fusión en su rama de trabajo. Esta opción también está disponible en git pull. Por lo tanto, puede hacer lo siguiente:
git pull --ff-only origin branchA #See if you can pull down and merge branchA
git merge --ff-only branchA branchB #See if you can merge branchA into branchB
Eso hará la fusión si se puede hacer con avance rápido, que no es lo que quería en la pregunta original. Creo que la respuesta aceptada tiene la otra mitad que la arregla.
Otto
Realmente, sin embargo, los avisos de git sofisticados obvian la necesidad que tengo de este tipo de cosas.
Otto
2
No es realmente lo mismo. Salir con un estado distinto de cero porque la fusión no se puede resolver ya que el avance rápido no significa que haya conflictos . Simplemente significa que la historia ha divergido y que es necesario un compromiso de fusión.
ADTC
7
Uso git log para ver qué ha cambiado en una rama de características desde la rama maestra
Si desea avanzar rápidamente de B a A, debe asegurarse de que git log B..A no muestre nada, es decir, A no tiene nada que B no tenga. Pero incluso si B..A tiene algo, es posible que pueda fusionarse sin conflictos, por lo que lo anterior muestra dos cosas: que habrá un avance rápido y, por lo tanto, no obtendrá un conflicto.
Verá si hay conflictos y puede planificar cómo resolverlos.
Después de eso, puede abortar la fusión a través de git merge --aborto (si no hubo conflictos y se ha producido la fusión) retroceder a la confirmación anterior a través degit reset --hard HEAD~1
Respuestas:
Como se señaló anteriormente, pase la
--no-commit
bandera, pero para evitar una confirmación de avance rápido, también pase--no-ff
, así:Para examinar los cambios organizados:
Y puede deshacer la fusión, incluso si es una fusión de avance rápido:
fuente
git merge --only-if-there-wont-be-any-conflicts
ogit diff --show-conflicts <commit>
sería realmente útil. Es una pena que todavía no sea posible, o me estoy perdiendo algogit pull --ff-only
!Simplemente tuve que implementar un método que encuentra automáticamente conflictos entre un repositorio y su control remoto. Esta solución se fusiona en la memoria para que no toque el índice ni el árbol de trabajo. Creo que esta es la forma más segura posible de resolver este problema. Así es como funciona:
git fetch origin master
git merge-base FETCH_HEAD master
git merge-tree mergebase master FETCH_HEAD
( mergebase es la identificación hexadecimal que merge-base imprimió en el paso anterior)Ahora suponga que desea fusionar el maestro remoto con su maestro local, pero puede usar cualquier rama.
git merge-tree
ejecutará la fusión en la memoria e imprimirá el resultado en la salida estándar. Grep para el patrón<<
o>>
. O puede imprimir el resultado en un archivo y verificarlo. Si encuentra una línea que comienza con 'cambiado en ambos', lo más probable es que haya un conflicto.fuente
git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
git merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"
simplemente increíble! +100+<<<<<<< .our
por lo tanto, uso una expresión grep comogrep -q '^+<* \.our$'
Mi solución simple de fuerza bruta para esto es:
Crear una rama "pre-master" (del maestro, por supuesto)
Combina todas las cosas que quieras en este pre-master.
Entonces puedes ver cómo ocurrió la fusión sin tocar al maestro.
De todos modos, seguiría el consejo de @ orange80.
fuente
git merge --abort
si hay conflictos,git reset --hard HEAD~1
si hubo una fusión ogit reset --hard origin/master
. Crear otra rama te da una sensación de seguridad, pero si aprendes cómo funciona git, entenderás que es un miedo fuera de lugar. Cuando la preocupación es por no cambiar la copia de trabajo, esto no ofrece solución.git merge --no-commit
no abortará una fusión si se puede reenviar rápidamente.git merge --abort
no funciona si se fusionó. Si desea escribir esto como un script, es incómodo, yagit merge
que no responde con códigos de error lo suficientemente buenos como para explicar los diferentes tipos de conflictos. Trabajar con una rama nueva evita que un script roto deje su repositorio en un estado que requiera intervención manual. Claro que no puedes perder nada. Pero es más fácil construir de otra manera.Deshacer una fusión con git es tan fácil que ni siquiera debería preocuparse por la ejecución en seco:
EDITAR: Como se señala en los comentarios a continuación, si tiene cambios en su directorio de trabajo o área de preparación, probablemente desee guardarlos antes de hacer lo anterior (de lo contrario, desaparecerán después de lo
git reset
anterior)fuente
git branch --contains HEAD
o incluso más directamente, solo usegit merge --ff-only
--dry-run
no "simplemente comprobaría si una fusión se adelantará". Devolvería el resultado exacto que haría una fusión: archivos, conflictos, etc. Si will ff no es realmente interesante, ¿verdad?git stash; git reset --hard
? @BrianPhillipsHice un alias para hacer esto y funciona de maravilla, hago esto:
Ahora solo llamo
Para averiguar si hay conflictos.
fuente
Simplemente diferencie su rama actual contra la rama remota, esto le dirá qué va a cambiar cuando haga una extracción / fusión.
fuente
Yo uso el comando request-pull git para hacerlo. Le permite ver cada cambio que sucedería al fusionar, pero sin hacer nada en sus repositorios locales o remotos .
Por ejemplo, imagine que desea fusionar una rama llamada "feature-x" en su rama maestra
le mostrará un resumen de lo que sucedería (sin hacer nada):
Si agrega el
-p
parámetro, también obtendrá el texto completo del parche, exactamente como si estuviera haciendo un git diff en cada archivo modificado.fuente
master
yorigin
hacer en las opciones de línea de comandos, y ¿qué pasa si estoy, por ejemplo, en un localbranch1
y quiero hacer unrequest-pull
en una rama de característica localbranch2
? ¿Aún lo necesitoorigin
? Por supuesto, uno siempre puede leer la documentación.Me sorprende que nadie haya sugerido usar parches todavía.
Digamos que usted desea probar una combinación de
your_branch
amaster
(estoy suponiendo que hayamaster
comprobado):Eso debería hacer el truco.
Si obtienes errores como
eso significa que el parche no tuvo éxito y una fusión produciría conflictos. Sin salida significa que el parche está limpio y podrá fusionar fácilmente la rama
Tenga en cuenta que esto realmente no cambiará su árbol de trabajo (aparte de crear el archivo de parche, por supuesto, pero puede eliminarlo de forma segura después). De la documentación de git-apply:
Nota para cualquiera que sea más inteligente / más experimentado con git que yo: avíseme si me equivoco aquí y este método muestra un comportamiento diferente al de una fusión regular. Parece extraño que en los más de 8 años que ha existido esta pregunta nadie sugiera esta solución aparentemente obvia.
fuente
git diff master your_branch | git apply --check
.Esto puede ser interesante: de la documentación:
Pero también puedes hacerlo de la manera ingenua (pero lenta):
(Nota: no funcionará simplemente clonando a / tmp, necesitará una copia para asegurarse de que los cambios no confirmados no entren en conflicto).
fuente
cp -r repository/.git /tmp/repository/.git
,cd /tmp/repository
,git reset --hard
,git add --all
,git reset --hard
(por si acaso),git status
(para comprobar que está limpio).Soy consciente de que esta es una pregunta antigua, pero es la primera en aparecer en una búsqueda de Google.
Git introdujo una opción --ff-only al fusionar.
Hacer esto intentará fusionarse y avanzar rápidamente, y si no puede, aborta y le indica que no se pudo realizar el avance rápido, pero deja intacta su rama de trabajo. Si puede avanzar rápidamente, realizará la fusión en su rama de trabajo. Esta opción también está disponible en
git pull
. Por lo tanto, puede hacer lo siguiente:fuente
Uso git log para ver qué ha cambiado en una rama de características desde la rama maestra
por ejemplo, para ver qué confirmaciones hay en una rama de características que se ha / no se ha fusionado para dominar:
fuente
Si desea avanzar rápidamente de B a A, debe asegurarse de que git log B..A no muestre nada, es decir, A no tiene nada que B no tenga. Pero incluso si B..A tiene algo, es posible que pueda fusionarse sin conflictos, por lo que lo anterior muestra dos cosas: que habrá un avance rápido y, por lo tanto, no obtendrá un conflicto.
fuente
Mi solución es fusionarme al revés.
En lugar de fusionar su rama en la rama "objetivo" remota, combine esa rama con la suya.
Verá si hay conflictos y puede planificar cómo resolverlos.
Después de eso, puede abortar la fusión a través de git
merge --abort
o (si no hubo conflictos y se ha producido la fusión) retroceder a la confirmación anterior a través degit reset --hard HEAD~1
fuente
Haga una copia temporal de su copia de trabajo, luego combínela y difunda las dos.
fuente