Подтвердить что ты не робот

Git: Как отделить библиотеку от проекта? фильтр-ветвь, поддерево?

Итак, у меня есть проект с более крупным (закрытый исходный код), и в контексте этого проекта я создаю библиотеку, которая также может быть полезной в других местах. Я полагаю, что

Теперь я хочу отделить библиотеку от своего собственного проекта, который может стать открытым исходным кодом на github или аналогичном. Конечно, библиотека (и ее история там) не должна содержать следов нашего проекта.

git -subtree кажется здесь решением, но он не подходит.

Мой макет каталога похож на этот (так как это проект Java):

  • фехтование (git workdir)
    • ЦСИ
      • де
        • fencing_game
          • транспорт (моя библиотека)
            • протокол (часть библиотеки)
            • фехтование (часть основного проекта, связанного с библиотекой)
            • клиент (часть основного проекта, связанного с библиотекой)
            • сервер (часть основного проекта, связанного с библиотекой)
          • клиент (часть основного проекта)
          • сервер (часть основного проекта)
          • ... (часть основного проекта)
    • другие файлы и каталоги (система сборки, веб-сайт и т.д. - часть основного проекта)

После разделения я хочу, чтобы макет каталога библиотеки выглядел так (включая любые файлы непосредственно в жирных каталогах):

  • my-library (имя будет определено)
    • ЦСИ
      • де
        • fencing_game
          • транспорт (моя библиотека)
            • протокол (часть библиотеки)

История также должна содержать только часть основной истории проекта, которая затрагивает эту часть репозитория.

Первый взгляд показал мне git-subtree split --prefix=src/de/fencing_ame/transport, но это будет

  • дайте мне дерево, внедренное в transport (которое не будет компилироваться) и
  • включают каталоги transport/client, transport/server и transport/fencing.

Первая точка может быть уменьшена с помощью git subtree add --prefix=src/de/fencing_ame/transport <commit> на принимающей стороне, но я не думаю, что git -subtree может многое сделать против экспорта также этих подкаталогов. (Идея состоит в том, чтобы просто иметь возможность делиться полным деревом здесь).

Нужно ли здесь использовать git filter-branch?

После разделения я хочу иметь возможность импортировать библиотеку в свой основной проект, используя git -subtree или git -submodule в отдельном подкаталоге, а не там, где он сейчас. Я представляю макет таким образом

  • фехтование (git workdir)
    • ЦСИ
      • де
        • fencing_game
          • транспорт (пустой)
            • фехтование (часть основного проекта, связанного с библиотекой)
            • клиент (часть основного проекта, связанного с библиотекой)
            • сервер (часть основного проекта, связанного с библиотекой)
          • клиент (часть основного проекта)
          • сервер (часть основного проекта)
          • ... (часть основного проекта)
    • моя библиотека
      • ЦСИ
        • де
          • fencing_game
            • транспорт (моя библиотека)
              • протокол (часть библиотеки)
    • другие файлы и каталоги (система сборки, веб-сайт и т.д. - часть основного проекта)
Что было бы самым безболезненным способом сделать это? Существуют ли другие инструменты, чем git -subtree и git -filter-branch для этой цели?
4b9b3361

Ответ 1

Я думаю, что у вас есть реальный спелеолог. Если вы просто хотите отделить "протокол", вы можете сделать это с помощью "git разделов поддерева..." или "git filter-branch..."

git filter-branch --subdirectory-filter fencing-game/src/de/fencing_game/transport/protocol -- --all

Но если у вас есть файлы на транспорте, а также транспорт/протокол, он начинает становиться волосатым.

Я написал несколько специальных инструментов, чтобы сделать это для проекта, в котором я был. Они нигде не публикуются, но вы можете сделать что-то подобное с reposurgeon.

Ответ 2

Разделение поддерева, смешанного с файлами из родительского проекта

Это, кажется, общий запрос, однако я не думаю, что существует простой ответ, когда папки смешаны вместе.

Общий метод, который я предлагаю разделить библиотеку, смешанную с другими папками, таков:

  • Создайте ветку с новым корнем для библиотеки:

    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
    
  • Затем используйте что-то, чтобы перезаписать историю, чтобы удалить части, которые не являются частью библиотеки. Я не эксперт в этом, но я смог экспериментировать и нашел что-то вроде этого:

    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
    

    Примечание. Возможно, вам потребуется удалить резервную копию, созданную ветвью фильтра между последовательными командами.

    git update-ref -d refs/original/refs/heads/temp-br
    
  • Наконец, просто создайте новое репо для библиотеки и потяните все, что осталось:

    cd <new-lib-repo>
    git init
    git pull <original-repo> temp-br
    

Я рекомендую, чтобы ваш конечный путь библиотеки был больше похож на /transport/protocol вместо полного пути родительского проекта, поскольку это похоже на привязку к проекту.

Ответ 3

Проблема здесь в том, что нет хорошего разделения того, что есть и не является частью вашей библиотеки. Я бы настоятельно рекомендовал, чтобы решение было реорганизовано, а затем вы можете просто включить библиотеку в качестве подмодуля.

Если повторное использование этой библиотеки будет только в том же репо другими разработчиками, просто отслеживайте эти изменения на отдельной ветке и не беспокойтесь о дополнительных репозиториях.

Ответ 4

Будет ли история проекта быть только для вашей выгоды или для людей на github?

Если история только для вашей выгоды, есть простой способ использования трансплантатов. В принципе, просто создайте новый репозиторий для github, удалив все проприетарный код. Теперь у вас есть репозиторий с открытым исходным кодом с открытым кодом, который вы можете нажать на github. В вашей локальной копии репозитория с открытым исходным кодом вы можете перенести историю с собственного репо на репозиторий с открытым исходным кодом.

Выполнение этого способа означает, что вы (или любой, у кого есть доступ к собственному репо), имеют возможность увидеть полную историю, но широкая публика увидит код только с того момента, когда вы открываете его.

Что такое .git/info/grafts для?

Ответ 5

Я сделал что-то подобное, но разделил несколько разделов вещей на совершенно отдельный репо на зашифрованном разделе (/secure/tmp/newrepo), поэтому они не были доступны для вора ноутбука. Я написал оболочку script, а затем сделал: git filter-branch --tree-filter '~/bin/tryit/secure/tmp/newrepo личное личное' - 95768021ff00216855868d12556137115b2789610..HEAD(SHA избегает коммитов до того, как какой-либо каталог выйдет из строя)


#!/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

Для ваших целей вы, вероятно, захотите иметь другую спецификацию для tar (например, --exclude =), а затем использовать cat ${LIST} | xargs rm, чтобы удалить материал только в tar, но, надеясь, это не слишком сложно.

Неисправный материал и выход 0 важны, поскольку ветвь фильтра устанавливает их в исходное репо (не то, что вы хотите!), и умрет, если sh передает ненужный код выхода из последней команды в вашем script.