tag - git: ¿Cómo separar la biblioteca del proyecto? filtro-rama, subárbol?
que es head en git (5)
División de un subárbol mezclado con archivos del proyecto principal
Esto parece ser una solicitud común, sin embargo, no creo que haya una respuesta simple , cuando las carpetas se mezclan de esa manera.
El método general que sugiero para dividir la biblioteca mezclada con otras carpetas es este:
Haz una rama con la nueva raíz para la biblioteca:
git subtree split -P src/de/fencing_game -b temp-br git checkout temp-br # -or-, if you really want to keep the full path: git checkout -b temp-br cd src/de/fencing_game
Luego, use algo para volver a escribir el historial y eliminar las partes que no forman parte de la biblioteca. No soy experto en esto, pero pude experimentar y encontré algo como esto para trabajar:
git filter-branch --tag-name-filter cat --prune-empty --index-filter ''git rm -rf --cached --ignore-unmatch client server otherstuff'' HEAD # also clear out stuff from the sub dir cd transport git filter-branch --tag-name-filter cat --prune-empty --index-filter ''git rm -rf --cached --ignore-unmatch fencing client server'' HEAD
Nota: Es posible que deba eliminar la copia de seguridad realizada por la rama de filtro entre los comandos sucesivos.
git update-ref -d refs/original/refs/heads/temp-br
Por último, simplemente cree un nuevo repositorio para la biblioteca y extraiga todo lo que queda:
cd <new-lib-repo> git init git pull <original-repo> temp-br
Recomiendo que la ruta final de la biblioteca sea más parecida a /transport/protocol
lugar de la ruta principal del proyecto, ya que parece estar unida al proyecto.
Entonces, tengo un proyecto más grande (de código cerrado), y en el contexto de este proyecto, creé una biblioteca que también podría ser útil en otros lugares, creo.
Ahora quiero separar la biblioteca en su propio proyecto, que podría ir como código abierto en github o similar. Por supuesto, la biblioteca (y su historia allí) no debe contener rastros de nuestro proyecto.
El git-subárbol parece una solución aquí, pero no encaja completamente.
El diseño de mi directorio es algo así (ya que es un proyecto Java):
- juego de esgrima (git workdir)
- src
- Delaware
- juego de esgrima
- transporte (mi biblioteca)
- protocolo (parte de la biblioteca)
- Esgrima (parte del proyecto principal que interactúa con la biblioteca)
- cliente (parte del proyecto principal que interactúa con la biblioteca)
- servidor (parte del proyecto principal que interactúa con la biblioteca)
- cliente (parte del proyecto principal)
- servidor (parte del proyecto principal)
- ... (parte del proyecto principal)
- transporte (mi biblioteca)
- juego de esgrima
- Delaware
- Otros archivos y directorios (sistema de compilación, sitio web y demás, parte del proyecto principal)
- src
Después de la división, quiero que el diseño del directorio de la biblioteca tenga este aspecto (incluidos los archivos directamente en los directorios en negrita):
- mi biblioteca (nombre por determinar)
- src
- Delaware
- juego de esgrima
- transporte (mi biblioteca)
- protocolo (parte de la biblioteca)
- transporte (mi biblioteca)
- juego de esgrima
- Delaware
- src
El historial también debe contener solo la parte del historial del proyecto principal que toca esta parte del repositorio.
Un primer vistazo me mostró la git-subtree split --prefix=src/de/fencing_ame/transport
, pero esto lo hará
- Dame un árbol enraizado en el
transport
(que no compilará) y - incluye los directorios de
transport/client
,transport/server
ytransport/fencing
.
El primer punto podría ser mitigado usando el git subtree add --prefix=src/de/fencing_ame/transport <commit>
en el lado receptor, pero no creo que git-subárbol pueda hacer mucho contra la exportación también de estos subdirectorios. (La idea realmente es poder compartir el árbol completo aquí).
¿Tengo que usar git filter-branch
aquí?
Después de la división, quiero poder volver a importar la biblioteca en mi proyecto principal, ya sea usando git-subárbol o git-submódulo, en un subdirectorio separado en lugar de donde está ahora. Me imagino el diseño de esta manera
- juego de esgrima (git workdir)
- src
- Delaware
- juego de esgrima
- transporte (vacío)
- Esgrima (parte del proyecto principal que interactúa con la biblioteca)
- cliente (parte del proyecto principal que interactúa con la biblioteca)
- servidor (parte del proyecto principal que interactúa con la biblioteca)
- cliente (parte del proyecto principal)
- servidor (parte del proyecto principal)
- ... (parte del proyecto principal)
- transporte (vacío)
- juego de esgrima
- Delaware
- mi biblioteca
- src
- Delaware
- juego de esgrima
- transporte (mi biblioteca)
- protocolo (parte de la biblioteca)
- transporte (mi biblioteca)
- juego de esgrima
- Delaware
- src
- Otros archivos y directorios (sistema de compilación, sitio web y demás, parte del proyecto principal)
- src
¿La historia del proyecto será solo para su beneficio o para el beneficio de las personas en github?
Si el historial es solo para su beneficio, existe una forma sencilla de utilizar los injertos. Básicamente, simplemente cree un nuevo repositorio para github, eliminando todo el código propietario. Ahora tiene un repositorio de código abierto con solo código público que puede enviar a github. En su copia local del repositorio de código abierto, puede injertar el historial del repositorio propietario en el repositorio de código abierto.
Hacerlo de esta manera significa que usted (o cualquier persona con acceso al repositorio privado) tiene la ventaja de ver el historial completo, pero el público en general solo verá el código desde el momento en que lo abra.
Creo que tienes algo de espeluznante que hacer. Si solo quiere separar el "protocolo", puede hacerlo con "git subárbol dividido ..." o "git filter-branch ..."
git filter-branch --subdirectory-filter fencing-game/src/de/fencing_game/transport/protocol -- --all
Pero si tiene archivos en transporte así como en transporte / protocolo, comienza a ponerse peludo.
Escribí algunas herramientas personalizadas para hacer esto para un proyecto en el que estaba. No se publican en ninguna parte, pero se puede hacer algo similar con la reposurgeon .
El problema aquí es que no hay una buena separación de lo que es y no es parte de su biblioteca. Yo sugeriría encarecidamente que la solución se refactorice y luego simplemente puede incluir la biblioteca como un submódulo.
Si la reutilización de esta biblioteca estará en el mismo repositorio de otros desarrolladores, solo rastree esos cambios en una rama separada y no se moleste con repositorios adicionales.
He hecho algo similar, pero dividiendo varias direcciones de cosas en un repositorio completamente separado en una partición encriptada (/ secure / tmp / newrepo), por lo que no estaban disponibles para un ladrón de computadoras portátiles. Escribí el script de shell y luego lo hice: git filter-branch --tree-filter ''~ / bin / tryit / secure / tmp / newrepo personal private'' - 95768021ff00216855868d12556137115b2789610..HEAD (el SHA evita que el directorio comience a existir )
#!/bin/sh
# to be used with e.g:
# git filter-branch --tree-filter ''~/bin/tryit /secure/tmp/newrepo personal private''
# Don''t do it on any repository you can''t repeatedly do:
# rm -rf foo ; git clone /wherever/is/foo
# when it breaks
SRC=`pwd`
DEST=$1
shift
MSG=/dev/shm/msg.txt
TAR=/dev/shm/tmp.tar
LIST=/dev/shm/list.txt
LOG=/dev/shm/log
DONE=''''
echo $GIT_AUTHOR_DATE >> $LOG
git show --raw $GIT_COMMIT > $MSG
for A in $*
do
if [ -d $A ]
then
DONE=${DONE}x
tar -cf $TAR $A
tar -tf $TAR > ${LIST}
cat ${LIST} >> ${LOG}
rm -rf ${A}
cd ${DEST}
tar -xf $TAR
else
echo $A non-existant >> ${LOG}
fi
cd $SRC
done
if [ -z "${DONE}" ]
then
echo Empty >>$LOG
else
cd ${DEST}
unset GIT_INDEX_FILE
unset GIT_DIR
unset GIT_COMMIT
unset GIT_WORK_TREE
touch foo
git add .
git commit -a -F ${MSG} >> ${LOG}
fi
exit 0
Para sus propósitos, probablemente querrá tener una especificación diferente para el alquitrán (por ejemplo, --exclude =) y luego usar cat $ {LIST} | xargs rm solo remueve cosas del alquitrán, pero espero que hacerlo no sea demasiado complicado.
Las cosas sin configurar y la salida 0 son importantes, ya que las ramas de filtro las establecen en el repositorio de origen (¡no es lo que quieres!) Y morirán si sh pasa un código de salida distinto de cero del último comando de tu script.