Создать новый репозиторий Git из текущего HEAD, установить его как удаленный от исходного и отразить будущие изменения в обоих репозиториях? - PullRequest
0 голосов
/ 09 декабря 2018

Текущий репозиторий имеет коммиты

  A -> B -> C
            ^
            |
         HEAD

Я хочу создать новый репозиторий, основная ветвь которого начинается с коммита C (HEAD) текущего репозитория.

  C
  ^
  |
HEAD

Кроме того, если в текущий репозиторий добавлен новый коммит D:

  A -> B -> C -> D
                 ^
                 |
                HEAD

Новый репозиторий станет:

  C -> D
       ^
       |
      HEAD

Вкл.следующий толчок / зеркало.

Из-за того, что я научился разрабатывать программное обеспечение, пока я вносил изменения в проект, размер хранилища увеличился из-за добавления и удаления больших файлов в течение его длинной истории (500 подтверждений).

Можетэтот рабочий процесс может быть легко достигнут в git?(С использованием GitHub и GitLab)

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

То, что вы пытаетесь сделать, почти невозможно.В git история, ведущая к данному коммиту, является неотъемлемой частью этого коммита.Таким образом, коммиты, обозначенные C в следующих двух историях

  A -> B -> C
            ^
            |
         HEAD

и

  C
  ^
  |
HEAD

, на самом деле являются двумя разными объектами коммитов, скорее всего, с двумя отдельными хешами.Единственный способ достичь желаемой настройки - настроить эти два разных объекта коммита на одинаковое значение хеш-функции, и в этом случае вы можете обмануть git, запихивая новые коммиты на основе C в разные репозитории с разными предысториями.Это может быть достигнуто в теории, но вряд ли на практике (если вам удастся это сделать, то вы также сможете взломать документы с цифровой подписью или изменить цепочку биткойнов).

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

old_repo_branch:      A -> B -> C ---->  D' -> E'
                                         ^     ^
                                        /     /
                                       /     /
new_repo_branch:                C' -> D --> E

Вам придется отправить new_repo_branch в новый репозиторий и old_repo_branch в старый репозиторий.Но таким потоком будет трудно управлять, если вам нужно разветвить свою разработку (поскольку каждый из параллельных потоков разработки должен быть разветвленным, и каждая пара соответствующих ветвей также должна быть синхронизирована).

0 голосов
/ 21 декабря 2018

Преамбула

Вы действительно должны рассмотреть свой рабочий процесс.Скорее всего, вы пытаетесь добиться странного рабочего процесса, скопированного с какой-то древней VCS.Git используется для отслеживания истории и позволяет вам переписать ее.Но вам нужно принять решение, какую историю вы хотите.Выполнение управления вариантами в отношении истории, вероятно, является плохой идеей.

500 commit - не большое значение для Git, ядро ​​Linux получило около 63.000 (!) Коммитов только в 2018 году ;)

Решение

Тем не менее, вот хакерское доказательство концепции, которая отвечает вашим потребностям.Нет необходимости в выделенном репозитории, переписанная история просто хранится в какой-то отдельной ветке.Первый запуск создаст эту потерянную ветвь, последующие запуска обновят ее последними коммитами.Оба вызова выглядят одинаково:

$ path/to/crazy-rebase <rewritten-branch> <last-commit-to-transfer>

Например:

$ ./crazy-rebase cutoff master

Как это работает

Во время первого запуска сценарий создает потерянную ветвь (например, cutoff) из данной ревизии (например, master) без какой-либо предыдущей истории.Все дальнейшие запуски будут выбирать все коммиты (пока не присутствующие) в эту потерянную ветвь (используя ребаз).Необходимые коммиты выводятся из последнего успешного завершения (на самом деле это хранится в специальной ссылке CUTOFF_BASE).

Script crazy-rebase:

#!/usr/bin/env bash

CUTOFF="$1"
CURRENT="$2"

LAST_BASE="CUTOFF_BASE"


error() {
    local errcode=$?
    echo "ERR: $*" >&2
    exit $errcode
}

log() {
    echo "LOG: $*" >&2
}

ret() {
    return "$1"
}


prepare() {
    local cutoff="$1"
    local current="$2"
    local base_hash

    git show-ref --quiet "$cutoff" &&
    return 0

    log "Preparing cut-off branch '$cutoff' ..." &&
    base_hash="`git show -s --pretty=%H "$current"`" &&
    git checkout --quiet --orphan="$cutoff" "$current" &&
    git commit -m "Cutoff branch, based on '$base_hash'" &&
    git checkout --quiet "$current" &&
    git update-ref "$LAST_BASE" "$base_hash" &&
    log "Cut off branch '$cutoff' created." &&
    exit 0 ||
    error "Failed to init cut-off branch '$cutoff'."
}

rebase() {
    local cutoff="$1"
    local current="$2"
    local current_hash
    local errcode

    log "Rebasing commits '$LAST_BASE..$current' onto cut-off branch '$cutoff' ..."
    current_hash="`git show -s --pretty=%H "$current"`" &&
    git rebase --rebase-merges --onto "$cutoff" "$LAST_BASE" "$current_hash" || {
        errcode=$?
        log "STARTING INTERACTIVE SHELL TO RESOLVE REBASE."
        log "Use 'git rebase --continue' after resolving the issue e.g. with 'git mergetool'."
        log "Do not forget to exit this shell to continue the script."
        $SHELL
        if test -e "`git rev-parse --git-dir`/rebase-merge"; then
            git rebase --abort 2>/dev/null
            git checkout --quiet "$current"
            ret $errcode
            error "Failed to transfer commits '$LAST_BASE..$current' to '$cutoff'."
        fi
    } &&
    git rebase --rebase-merges HEAD "$cutoff" &&
    git checkout --quiet "$current" &&
    git update-ref "$LAST_BASE" "$current" &&
    log "Cut-off branch '$cutoff' updated." &&
    true
}


prepare "$CUTOFF" "$CURRENT" &&
rebase "$CUTOFF" "$CURRENT" &&
true

Используйте это, если вы хотитеотправить результат в удаленное хранилище:

$ git push <remote> cutoff:<name-of-cutoff-on-remote>
0 голосов
/ 09 декабря 2018

Вы можете легко создать новый репо из существующего, по крайней мере, локально: просто git clone <src repo> [dest dir] (возможно, используя --depth или подобное, чтобы сэкономить на размере, хотя это сопровождается предостережениями, см. руководство * 1004).* для деталей).Однако заставить этот новый репозиторий автоматически следовать истории оригинала будет нелегко.Новый репо будет иметь настройку origin, чтобы указывать на оригинал, но обновление потребует извлечения / извлечения + слияния / чего угодно, как обычно.Возможно, вам удастся установить какой-либо хук после коммита в старом репо для автоматизации бита cd <new repo> ; git pull ; cd $OLDPWD, я не очень разбираюсь в том, как работают хиты git.С другой стороны, вы можете настроить новое репо как удаленное в старом и нажать на него, хотя я не уверен, как это повлияет на рабочее дерево нового репо (т. Е. Что проверено).И выполнение любой из этих работ с удаленным провайдером, таким как GitHub, было бы совершенно другой червью.

Если вы хотите попробовать очистить свою историю, вы можете захотеть взглянуть на rebase и, возможно, cherry-pick.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...