Estoy usando el subárbol de Git con un par de proyectos en los que estoy trabajando, para compartir un código base entre ellos. El código base se actualiza con frecuencia, y las actualizaciones pueden ocurrir en cualquiera de los proyectos, y eventualmente todos se actualizan.
Me encontré con un problema en el que git informa que mi subárbol está actualizado, pero se rechaza la inserción. Por ejemplo:
#! git subtree pull --prefix=public/shared project-shared master
From github.com:****
* branch master -> FETCH_HEAD
Already up-to-date.
Si presiono, debería recibir un mensaje de que no hay nada que presionar ... ¿Verdad? ¿CORRECTO? :(
#! git subtree push --prefix=public/shared project-shared master
git push using: project-shared master
To [email protected]:***
! [rejected] 72a6157733c4e0bf22f72b443e4ad3be0bc555ce -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:***'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
¿Cuál podría ser la razón de ésto? ¿Por qué está fallando el empuje?
git
git-subtree
mateusz
fuente
fuente
--rejoin
para acelerar los empujes de subárboles. Cuando paso por el subárbol de empuje manualmente, en ejecuciónsubtree split --rejoin
, la rama del subárbol dividido solo tiene un historial hasta la última reunión, cuando normalmente contiene todo el historial del subárbol. Para mí, esa es la causa inmediata del error que no es de avance rápido. Todavía no estoy seguro de por qué la división del subárbol genera un historial truncado.Respuestas:
Encontré la respuesta en este comentario de blog https://coderwall.com/p/ssxp5q
fuente
error: unknown option 'prefix'
heroku
y qué relaciónpythonapp
tengo en la respuesta. Traduciendo esto del lenguaje específico de Heroku:git push <your subtree's origin> `git subtree split --prefix=Path/to/subtree master`:master --force
En Windows, el comando anidado no funciona:
Primero puede ejecutar el bit anidado:
Esto (después de muchos números) devolverá un token, por ejemplo
Use esto en el comando contenedor, por ejemplo:
fuente
git subtree
no es un comando antes. Después de usar su solución, pude implementar una carpeta en heroku en lugar de todo mi repositorioUsa la
--onto
bandera:[EDITAR: desafortunadamente
subtree push
no reenvía--onto
al subyacentesplit
, por lo que la operación debe realizarse en dos comandos. Una vez hecho esto, veo que mis comandos son idénticos a los de una de las otras respuestas, pero la explicación es diferente, así que lo dejaré aquí de todos modos.]O si no está usando bash:
Pasé horas estudiando detenidamente la fuente de git-subtree para averiguarlo, así que espero que lo aprecies;)
subtree push
comienza ejecutandosubtree split
, lo que reescribe su historial de confirmaciones en un formato que debería estar listo para ser enviado. La forma en que lo hace es quepublic/shared/
quita el frente de cualquier ruta que lo tenga y elimina cualquier información sobre los archivos que no lo tienen. Eso significa que incluso si extrae no aplastado, todas las confirmaciones del sub-repositorio ascendente se ignoran ya que nombran los archivos por sus rutas desnudas. (Compromisos que no tocan ningún archivo debajopublic/shared/
, o fusionar confirmaciones que son idénticas a un padre, también se contraen. [EDITAR: Además, desde entonces encontré algo de detección de aplastamiento, así que ahora estoy pensando que es solo si tiraste sin aplastar, y luego el colapso de confirmación de fusión simplista descrito en otra respuesta logra elegir el camino no aplastado y descarte la ruta aplastada.]) El resultado es que las cosas que intenta impulsar terminan conteniendo cualquier trabajo que alguien haya comprometido con el repositorio de host actual desde el que está presionando, pero no las personas de trabajo comprometidas directamente con el sub-repositorio o mediante otro host repositorio.Sin embargo, si las usa
--onto
, todas las confirmaciones ascendentes se registran como correctas para usarlas literalmente, por lo que cuando el proceso de reescritura las encuentra como uno de los padres de una fusión que quiere reescribir, las mantendrá en lugar de intentar reescribirlas. de la forma habitual.fuente
git remote -v
.--onto
opción ayuda a git a identificar las confirmaciones que ya están en el repositorio secundario.Para una aplicación de tipo "GitHub pages", en la que implementas un subárbol "dist" en una rama de gh-pages, la solución podría verse así
Menciono esto porque se ve ligeramente diferente de los ejemplos de heroku dados anteriormente. Puede ver que mi carpeta "dist" existe en la rama maestra de mi repositorio, y luego la empujo como un subárbol a la rama gh-pages que también está en origen.
fuente
También me he encontrado con este problema antes, y así es como lo resolví.
Lo que descubrí fue que tenía una rama que no estaba adjunta a la rama principal local. Esta rama existe y está colgando en el vacío. En tu caso, probablemente se llame
project-shared
. Suponiendo que este sea el caso y cuando lo hagagit branch
, puede ver unaproject-shared
rama local , entonces puede ' agregar ' nuevas confirmaciones a suproject-shared
rama existente haciendo:git subtree split --prefix=public/shared --onto public-shared --branch public-shared
La forma en que entendí es
git subtree
que comenzará a crear una nueva rama--onto
, en este caso, es lapublic-shared
rama local . Entonces la rama significa crear una rama, que simplemente reemplaza lapublic-shared
rama anterior.Esto mantendrá todo el SHA anterior de la
public-shared
sucursal. Finalmente, puedes hacer ungit push project-shared project-shared:master
Suponiendo que también tenga un
project-shared
control remoto; esto empujará el local que cuelga en laproject-shared
rama vacía hacia lamaster
rama del control remotoproject-shared
.fuente
Esto se debe a la limitación del algoritmo original. Al manejar fusiones-confirmaciones, el algoritmo original usa un criterio simplificado para cortar a los padres no relacionados. En particular, comprueba si hay un padre que tiene el mismo árbol. Si tal padre lo encuentra, colapsaría la confirmación de fusión y usaría la confirmación padre en su lugar, asumiendo que otros padres tienen cambios no relacionados con el subárbol. En algunos casos, esto daría como resultado la eliminación de partes del historial, que tienen cambios reales en el subárbol. En particular, eliminaría secuencias de confirmaciones, que tocarían un subárbol, pero darían como resultado el mismo valor de subárbol.
Veamos un ejemplo (que puede reproducir fácilmente) para comprender mejor cómo funciona esto. Considere el siguiente historial (el formato de línea es: commit [árbol] asunto):
En este ejemplo, nos dividimos
dir
. ConfirmaD
yE
tiene el mismo árbolz
, porque tenemos confirmaciónC
, que deshizo la confirmaciónB
, por lo que laB-C
secuencia no hace nada adir
pesar de que tiene cambios.Ahora hagamos la división. Primero nos dividimos en el compromiso
C
.A continuación, dividimos el compromiso
E
.Sí, perdimos dos confirmaciones. Esto da como resultado el error al intentar empujar la segunda división, ya que no tiene esas dos confirmaciones, que ya llegaron al origen.
Por lo general, puede tolerar este error mediante el uso
push --force
, ya que las confirmaciones descartadas generalmente no contienen información crítica. A largo plazo, el error debe corregirse, por lo que el historial dividido en realidad tendría todas las confirmaciones, que se tocandir
, como se esperaba. Esperaría que la solución incluyera un análisis más profundo de los compromisos de los padres para las dependencias ocultas.Como referencia, aquí está la parte del código original, responsable del comportamiento.
copy_or_skip() ... for parent in $newparents; do ptree=$(toptree_for_commit $parent) || exit $? [ -z "$ptree" ] && continue if [ "$ptree" = "$tree" ]; then # an identical parent could be used in place of this rev. identical="$parent" else nonidentical="$parent" fi ... if [ -n "$identical" ]; then echo $identical else copy_commit $rev $tree "$p" || exit $? fi
fuente
La respuesta de Eric Woodruff no me ayudó, pero lo siguiente sí:
Por lo general, 'git subtree pull' con la opción '--squash'. Parece que esto hizo que las cosas fueran más difíciles de reconciliar, por lo que necesitaba hacer una extracción de subárbol sin aplastar esta vez, resolver algunos conflictos y luego presionar.
Debo agregar que el tirón aplastado no reveló ningún conflicto, me dijo que todo estaba bien.
fuente
Otra solución [más simple] es hacer avanzar la cabeza del control remoto haciendo otra confirmación si puede. Después de colocar este cabezal avanzado en el subárbol local, podrá volver a empujarlo.
fuente
Puede forzar la inserción de cambios locales en el repositorio de subárbol remoto
fuente
Powershell rápido para usuarios de Windows basado en la solución de Chris Jordan
fuente
Así que esto es lo que escribí basado en lo que dijo @entheh.
fuente
También tuve este problema. Esto es lo que hice, según las principales respuestas:
Dado:
Ingrese esto:
Tenga en cuenta que el token generado por 'git subtree push' se usa en 'git push'.
fuente