tipos tag remove practices etiquetas crear best git git-submodules

tag - Desmodular un submódulo git.



git tag best practices (11)

¿Cómo descompongo un submódulo de git (devuelvo todo el código al núcleo)?

Como en cómo "debería" yo, como en "Mejor procedimiento" ...


  1. git rm --cached the_submodule_path
  2. elimine la sección de submódulos del archivo .gitmodules , o si es el único submódulo, elimine el archivo.
  3. hacer un commit "eliminado submódulo xyz"
  4. git add the_submodule_path
  5. otro commit "añadido codebase de xyz"

No encontré ninguna manera más fácil todavía. Puede comprimir 3-5 en un solo paso a través de git commit -a - cuestión de gustos.


Aquí hay una versión ligeramente mejorada (IMHO) de la respuesta principal actual:

En un directorio separado (para hacer que los errores sean más fáciles de limpiar e intentar nuevamente) revisa tanto el repositorio superior como el subrepo.

git clone ../main_repo main.tmp git clone ../main_repo/sub_repo sub.tmp

Primero edite el subrepo para mover todos los archivos al subdirectorio deseado

cd sub.tmp mkdir sub_repo_path git mv `ls | grep -v sub_repo_path` sub_repo_path/ git commit -m "Moved entire subrepo into sub_repo_path"

Toma nota de la CABEZA

SUBREPO_HEAD=`git reflog | awk ''{ print $1; exit; }''`

Ahora quita el subrepo del repositorio principal

cd ../main.tmp rmdir sub_repo_path vi .gitmodules # remove config for submodule git add -A git commit -m "Removed submodule sub_repo_path in preparation for merge"

Y finalmente, simplemente fusionarlos

git fetch ../sub.tmp git merge $SUBREPO_HEAD

¡Y hecho! Con seguridad y sin magia.


Basado en la respuesta de VonC , he creado un simple script de bash que hace esto. El add al final tiene que usar comodines, de lo contrario, deshará el rm anterior para el submódulo. Es importante agregar el contenido del directorio de submódulos y no nombrar el directorio en sí en el comando add .

En un archivo llamado git-integrate-submodule :

#!/usr/bin/env bash mv "$1" "${1}_" git submodule deinit "$1" git rm "$1" mv "${1}_" "$1" git add "$1/**"


Desde git 1.8.5 (noviembre de 2013 ) ( sin guardar la historia del submódulo ):

mv yoursubmodule yoursubmodule_tmp git submodule deinit yourSubmodule git rm yourSubmodule mv yoursubmodule_tmp yoursubmodule git add yoursubmodule

Esa voluntad:

  • anular el registro y descargar (es decir, eliminar el contenido de ) el submódulo ( deinit , de ahí el mv primero ),
  • limpia los .gitmodules para ti ( rm ),
  • y elimine la entrada especial que representa ese submódulo SHA1 en el índice del repositorio principal ( rm ).

Una vez que se completa la eliminación del submódulo ( deinit y git rm ), puede cambiar el nombre de la carpeta a su nombre original y agregarla al repositorio de git como una carpeta normal.

Nota: si el submódulo fue creado por un Git antiguo (<1.8), es posible que deba eliminar la carpeta .git anidada dentro del propio submódulo, como lo commented Simon East.

Si necesita mantener el historial del submódulo, vea la answer jsears , que usa git filter-branch .


Hay muchas respuestas aquí, pero todas parecen ser demasiado complejas y es probable que no hagan lo que usted quiere. Estoy seguro de que la mayoría de la gente quiere mantener su historia.

Para este ejemplo, el repositorio principal será [email protected]:main/main.git y el repositorio de submódulos será [email protected]:main/child.git . Esto supone que el submódulo se encuentra en el directorio raíz del repositorio principal. Ajuste las instrucciones según sea necesario.

Comience por clonar el repositorio principal y eliminar el submódulo anterior.

git clone [email protected]:main/main.git git submodule deinit child git rm child git add --all git commit -m "remove child submodule"

Ahora agregaremos los repos del niño en sentido ascendente al repositorio principal.

git remote add upstream [email protected]:main/child.git git fetch upstream git checkout -b merge-prep upstream/master

El siguiente paso supone que desea mover los archivos en la rama de combinación de preparación a la misma ubicación que el submódulo que estaba arriba, aunque puede cambiar fácilmente la ubicación cambiando la ruta del archivo.

mkdir child

mueva todas las carpetas y archivos excepto la carpeta .git a la carpeta secundaria.

git add --all git commit -m "merge prep"

Ahora puede simplemente fusionar sus archivos de nuevo en la rama maestra.

git checkout master git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required

Mire a su alrededor y asegúrese de que todo se vea bien antes de ejecutar git push

Lo único que debes recordar ahora es que git log no sigue de forma predeterminada los archivos movidos; sin embargo, al ejecutar git log --follow filename , puedes ver el historial completo de tus archivos.


He creado un script que traducirá un submódulo a un directorio simple, al tiempo que conserva todo el historial de archivos. No sufre los problemas de git log --follow <file> que sufren las otras soluciones. También es una invocación de una línea muy fácil que hace todo el trabajo por ti. G''luck

Se basa en el excelente trabajo de Lucas Jenß, descrito en su entrada del blog " Integración de un submódulo en el repositorio principal ", pero automatiza todo el proceso y limpia algunos otros casos de esquina.

El código más reciente se mantendrá con las correcciones de errores en github en https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite , pero por el bien del protocolo de respuesta de adecuado, he incluido el Solución en su totalidad a continuación.

Uso:

$ git-submodule-rewrite <submodule-name>

git-submodule-rewrite

#!/usr/bin/env bash # This script builds on the excellent work by Lucas Jenß, described in his blog # post "Integrating a submodule into the parent repository", but automates the # entire process and cleans up a few other corner cases. # https://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html function usage(){ echo "Merge a submodule into a repo, retaining file history." echo "Usage: $0 <submodule-name>" echo "" echo "options:" echo " -h, --help Print this message" echo " -v, --verbose Display verbose output" } function abort { echo "$(tput setaf 1)$1$(tput sgr0)" exit 1 } function request_confirmation { read -p "$(tput setaf 4)$1 (y/n) $(tput sgr0)" [ "$REPLY" == "y" ] || abort "Aborted!" } function warn() { cat << EOF This script will convert your "${sub}" git submodule into a simple subdirectory in the parent repository while retaining all contents and file history. The script will: * delete the ${sub} submodule configuration from .gitmodules and .git/config and commit it. * rewrite the entire history of the ${sub} submodule so that all paths are prefixed by ${path}. This ensures that git log will correctly follow the original file history. * merge the submodule into its parent repository and commit it. NOTE: This script might completely garble your repository, so PLEASE apply this only to a fresh clone of the repository where it does not matter if the repo is destroyed. It would be wise to keep a backup clone of your repository, so that you can reconstitute it if need be. You have been warned. Use at your own risk. EOF request_confirmation "Do you want to proceed?" } function git_version_lte() { OP_VERSION=$(printf "%03d%03d%03d%03d" $(echo "$1" | tr ''.'' ''/n'' | head -n 4)) GIT_VERSION=$(git version) GIT_VERSION=$(printf "%03d%03d%03d%03d" $(echo "${GIT_VERSION#git version}" | tr ''.'' ''/n'' | head -n 4)) echo -e "${GIT_VERSION}/n${OP_VERSION}" | sort | head -n1 [ ${OP_VERSION} -le ${GIT_VERSION} ] } function main() { warn if [ "${verbose}" == "true" ]; then set -x fi # Remove submodule and commit git config -f .gitmodules --remove-section "submodule.${sub}" if git config -f .git/config --get "submodule.${sub}.url"; then git config -f .git/config --remove-section "submodule.${sub}" fi rm -rf "${path}" git add -A . git commit -m "Remove submodule ${sub}" rm -rf ".git/modules/${sub}" # Rewrite submodule history local tmpdir="$(mktemp -d -t submodule-rewrite-XXXXXX)" git clone "${url}" "${tmpdir}" pushd "${tmpdir}" local tab="$(printf ''/t'')" local filter="git ls-files -s | sed /"s/${tab}/${tab}${path}////" | GIT_INDEX_FILE=/${GIT_INDEX_FILE}.new git update-index --index-info && mv /${GIT_INDEX_FILE}.new /${GIT_INDEX_FILE}" git filter-branch --index-filter "${filter}" HEAD popd # Merge in rewritten submodule history git remote add "${sub}" "${tmpdir}" git fetch "${sub}" if git_version_lte 2.8.4 then # Previous to git 2.9.0 the parameter would yield an error ALLOW_UNRELATED_HISTORIES="" else # From git 2.9.0 this parameter is required ALLOW_UNRELATED_HISTORIES="--allow-unrelated-histories" fi git merge -s ours --no-commit ${ALLOW_UNRELATED_HISTORIES} "${sub}/master" rm -rf tmpdir # Add submodule content git clone "${url}" "${path}" rm -rf "${path}/.git" git add "${path}" git commit -m "Merge submodule contents for ${sub}" git config -f .git/config --remove-section "remote.${sub}" set +x echo "$(tput setaf 2)Submodule merge complete. Push changes after review.$(tput sgr0)" } set -euo pipefail declare verbose=false while [ $# -gt 0 ]; do case "$1" in (-h|--help) usage exit 0 ;; (-v|--verbose) verbose=true ;; (*) break ;; esac shift done declare sub="${1:-}" if [ -z "${sub}" ]; then >&2 echo "Error: No submodule specified" usage exit 1 fi shift if [ -n "${1:-}" ]; then >&2 echo "Error: Unknown option: ${1:-}" usage exit 1 fi if ! [ -d ".git" ]; then >&2 echo "Error: No git repository found. Must be run from the root of a git repository" usage exit 1 fi declare path="$(git config -f .gitmodules --get "submodule.${sub}.path")" declare url="$(git config -f .gitmodules --get "submodule.${sub}.url")" if [ -z "${path}" ]; then >&2 echo "Error: Submodule not found: ${sub}" usage exit 1 fi if ! [ -d "${path}" ]; then >&2 echo "Error: Submodule path not found: ${path}" usage exit 1 fi main


La mejor respuesta a esto que he encontrado está aquí:

x3ro.de/2013/09/01/…

Este artículo explica muy bien el procedimiento.


Me pareció más conveniente (también?) Obtener datos de confirmación local del submódulo, porque de lo contrario los perdería. (No pude empujarlos ya que no tengo acceso a ese control remoto). Así que agregué submódulo / .git como remote_origin2, obtuve los confirmados y los fusioné desde esa rama. No estoy seguro si todavía necesito el submódulo remoto como origen, ya que todavía no estoy lo suficientemente familiarizado con git.


Nos ocurrió que creamos 2 repositorios para 2 proyectos que estaban tan acoplados que no tenía sentido separarlos, así que los fusionamos.

Mostraré cómo fusionar las ramas maestras en cada una y luego explicaré cómo puede extender esto a cada una de las ramas que tiene, espero que le sirva de ayuda.

Si tiene el submódulo en funcionamiento y desea convertirlo en un directorio, puede hacerlo:

git clone project_uri project_name

Aquí hacemos un clon limpio para trabajar. Para este proceso no necesita inicializar o actualizar los submódulos, así que simplemente omítalo.

cd project_name vim .gitmodules

Edite .gitmodules con su editor favorito (o Vim) para eliminar el submódulo que planea reemplazar. Las líneas que necesitas eliminar deberían verse así:

[submodule "lib/asi-http-request"] path = lib/asi-http-request url = https://github.com/pokeb/asi-http-request.git

Después de guardar el archivo,

git rm --cached directory_of_submodule git commit -am "Removed submodule_name as submodule" rm -rf directory_of_submodule

Aquí eliminamos completamente la relación de submódulo para que podamos crear traer el otro repositorio al proyecto en el lugar.

git remote add -f submodule_origin submodule_uri git fetch submodel_origin/master

Aquí vamos a buscar el repositorio de submódulos para fusionar.

git merge -s ours --no-commit submodule_origin/master

Aquí comenzamos una operación de fusión de los 2 repositorios, pero paramos antes de confirmar.

git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master

Aquí enviamos el contenido del maestro en el submódulo al directorio donde estaba antes de prefijar un nombre de directorio

git commit -am "submodule_name is now part of main project"

Aquí completamos el procedimiento realizando una confirmación de los cambios en la combinación.

Después de terminar esto, puede presionar, y comenzar nuevamente con cualquier otra rama para fusionar, simplemente verifique la rama en su repositorio que recibirá los cambios y cambie la rama que traiga en las operaciones de fusión y lectura en árbol.


Para cuando

git rm [-r] --cached submodule_path

devoluciones

fatal: pathspec ''emr/normalizers/'' did not match any files

Contexto: realicé rm -r .git* en mis carpetas de submódulos antes de darme cuenta de que debían ser desmodificados en el proyecto principal al que acababa de agregarlos. Recibí el error anterior al descomponer algunos, pero no todos. De todos modos, los arreglé ejecutando, (después, por supuesto, el rm -r .git* )

mv submodule_path submodule_path.temp git add -A . git commit -m "De-submodulization phase 1/2" mv submodule_path.temp submodule_path git add -A . git commit -m "De-submodulization phase 2/2"

Tenga en cuenta que esto no conserva la historia.


Si todo lo que desea es poner su código de submódulo en el repositorio principal, solo necesita eliminar el submódulo y volver a agregar los archivos en el repositorio principal:

git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash) git rm .gitmodules # if you have more than one submodules, # you need to edit this file instead of deleting! rm -rf submodule_path/.git # make sure you have backup!! git add submodule_path # will add files instead of commit reference git commit -m "remove submodule"

Si también desea conservar el historial del submódulo, puede hacer un pequeño truco: "fusionar" el submódulo en el repositorio principal para que el resultado sea el mismo que antes, excepto que los archivos del submódulo ahora están en el repositorio principal.

En el módulo principal deberá hacer lo siguiente:

# Fetch the submodule commits into the main repository git remote add submodule_origin git://url/to/submodule/origin git fetch submodule_origin # Start a fake merge (won''t change any files, won''t commit anything) git merge -s ours --no-commit submodule_origin/master # Do the same as in the first solution git rm --cached submodule_path # delete reference to submodule HEAD git rm .gitmodules # if you have more than one submodules, # you need to edit this file instead of deleting! rm -rf submodule_path/.git # make sure you have backup!! git add submodule_path # will add files instead of commit reference # Commit and cleanup git commit -m "removed submodule" git remote rm submodule_origin

El repositorio resultante se verá un poco raro: habrá más de un compromiso inicial. Pero no causará ningún problema para git.

En esta segunda solución, tendrá la gran ventaja de que aún puede ejecutar git blame o git log en los archivos que estaban originalmente en los submódulos. De hecho, lo que hizo aquí es cambiar el nombre de muchos archivos dentro de un repositorio, y git debería autodetectar esto. Si aún tiene problemas con el registro de git, pruebe algunas opciones (--follow, -M, -C) que hacen un mejor cambio de nombre / detección de copia.