Создайте правильные Git-репозитории из Catchall (грязного) - PullRequest
0 голосов
/ 20 ноября 2018

Давайте назовем my-dirty-repository существующий Git-репозиторий, содержащий множество скриптов, которые не связаны между собой.Это универсальный репозиторий, который необходимо правильно очистить .

В качестве Минимального, Полного и Проверяемого примера , скажем, этот репозиторий содержит только:

script1.sh
script2.sh

С различными коммитами, которые независимо обновляли их, среди нескольких веток.

Целью является создание 2 100% независимых Git-репозиториев с ТОЛЬКО историей сохраненных файлов (ссылок).

Давайте назовем их my-clean-repository1 и my-clean-repository2, первый из которых имеет только историю о script1, а второй - только историю о script2.

Я пытался безуспешно достичь своих потребностей 3 способами:

Я уверен, что есть способ выполнить это правильно.

1 Ответ

0 голосов
/ 22 ноября 2018

Редактировать: Я создал специальный инструмент cloneToCleanGitRepositories на GitHub, чтобы удовлетворить эту потребность.

Это полная версия старой следующей.


@ mkasberg спасибо за ваши советы об интерактивной перебазировке, которая очень интересна в некоторой простой исторической ситуации.

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

В конце концов, для большинства из них этого оказалось недостаточно, и я снова попробовал другое решение с Системой фильтрации Git .

Наконец, янаписал этот небольшой скрипт:

#!/bin/bash
##
## Author: Bertrand Benoit <mailto:contact@bertrand-benoit.net>
## Description: Create clean git repositories for each file in root of specified source Git repository, updating history consequently. 
## Version: 1.0

[ $# -lt 2 ] && echo -e "Usage: $0 <source repository> <dest root directory>" >&2 && exit 1

SOURCE_REPO="$1"
[ ! -d "$SOURCE_REPO" ] && echo -e "Specified source Git repository '$SOURCE_REPO' does not exist." >&2 && exit 1
DEST_ROOT_DIR="$2"
[ ! -d "$DEST_ROOT_DIR" ] && echo -e "Specified destination root directory '$DEST_ROOT_DIR' does not exist." >&2 && exit 1

sourceRepoName=$( basename "$SOURCE_REPO" )

# For each file in root of the source git repository.
for refToManage in $( find "$SOURCE_REPO" -maxdepth 1 -type f ); do
  echo -ne "Managing $refToManage ... "

  refFileName=$( basename "$refToManage" )
  newDestRepo="$DEST_ROOT_DIR/$refFileName"

  # Creates the repository if not existing.
  logFile="$newDestRepo/logFile.txt"
  echo -ne "creating new repository: $newDestRepo, Log file: $logFile ... "
  if [ ! -d "$newDestRepo" ]; then
    mkdir -p "$newDestRepo"
    cd "$newDestRepo"
    ! git clone -q "$SOURCE_REPO" && echo -e "Error while cloning source repository to $newDestRepo." >&2 && exit 2
  fi
  cd "$newDestRepo/$sourceRepoName"

  # Removes all other resources.
  FILTER='git ls-tree -r --name-only --full-tree "$GIT_COMMIT" | grep -v "'$refFileName'" | tr "\n" "\0" | xargs -0 git rm -f --cached -r --ignore-unmatch'
  ! git filter-branch -f --prune-empty --index-filter "$FILTER" -- --all >"$logFile" 2>&1 && echo -e "Error while cleaning new git repository." >&2 && exit 3

  # Cleans remote information to ensure there is no push to the source repository.
  ! git remote remove origin >>"$logFile" 2>&1 && echo -e "Error while removing remote." >&2 && exit 2

  echo "done"
done

Использование:

mkdir /tmp/cleanRepoDest
createCleanGitRepo.sh ~/_gitRepo/Scripts /tmp/cleanRepoDest

В целевом каталоге он создаст новый чистый Git-репозиторий для КАЖДОГО файла в корневом каталоге указанного исходного Git-репозитория.В каждом из них история чиста и связана только с сохраненным сценарием.

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

Таким образом, легко «мигрировать» из большого грязного сборника Git Repository в различные чистые: -)

...