Как перемещать файлы из одного репозитория git в другой (не клон), сохраняя историю

Наши репозитории Git начинались как часть единственного репозитория SVN-монстра, в котором каждый отдельный проект имел свое собственное дерево:

project1/branches
        /tags
        /trunk
project2/branches
        /tags
        /trunk

Очевидно, было довольно легко перемещать файлы из одного в другое с помощью svn mv. Но в Git каждый проект находится в собственном репозитории, и сегодня меня попросили переместить подкаталог из project2 в project1. Я сделал что-то вроде этого:

$ git clone project2 
$ cd project2
$ git filter-branch --subdirectory-filter deeply/buried/java/source/directory/A -- --all
$ git remote rm origin  # so I don't accidentally the repo ;-)
$ mkdir -p deeply/buried/different/java/source/directory/B
$ for f in *.java; do 
>  git mv $f deeply/buried/different/java/source/directory/B
>  done
$ git commit -m "moved files to new subdirectory"
$ cd ..
$
$ git clone project1
$ cd project1
$ git remote add p2 ../project2
$ git fetch p2
$ git branch p2 remotes/p2/master
$ git merge p2 # --allow-unrelated-histories for git 2.9
$ git remote rm p2
$ git push

Но это кажется довольно запутанным. Есть ли лучший способ сделать это вообще? Или я принял правильный подход?

Обратите внимание, что это связано с объединением истории в существующий репозиторий, а не просто созданием нового автономного репозитория из части другого (как в более раннем вопросе).

Ответ 1

Да, нажатие на --subdirectory-filter of filter-branch было ключевым. Тот факт, что вы его использовали, по существу не доказывает, что нет более простого способа - у вас не было выбора, кроме как переписать историю, поскольку вы хотели получить только (переименованное) подмножество файлов, и это по определению изменяет хеши. Поскольку ни одна из стандартных команд (например, pull) не переписывает историю, вы не можете использовать их для достижения этой цели.

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

Ответ 2

Если ваша история работоспособна, вы можете взять коммиты в качестве патча и применить их в новом репозитории:

cd repository
git log --pretty=email --patch-with-stat --reverse --full-index --binary -- path/to/file_or_folder > patch
cd ../another_repository
git am < ../repository/patch 

Или в одной строке

git log --pretty=email --patch-with-stat --reverse -- path/to/file_or_folder | (cd /path/to/new_repository && git am)

(взято из Документов Exherbos)

Ответ 3

Перепробовав различные подходы для перемещения файла или папки из одного Git-репозитория в другой, единственный, который, кажется, работает надежно, описан ниже.

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

Первый этап

  1. Сделайте копию хранилища A, так как следующие шаги вносят существенные изменения в эту копию, которые вам не следует нажимать!

    git clone --branch <branch> --origin origin --progress \
      -v <git repository A url>
    # eg. git clone --branch master --origin origin --progress \
    #   -v https://[email protected]/scm/projects/myprojects.git
    # (assuming myprojects is the repository you want to copy from)
    
  2. CD в это

    cd <git repository A directory>
    #  eg. cd /c/Working/GIT/myprojects
    
  3. Удалите ссылку на исходный репозиторий, чтобы избежать случайного внесения каких-либо удаленных изменений (например, путем нажатия)

    git remote rm origin
    
  4. Просматривайте свою историю и файлы, удаляя все, что не находится в каталоге 1. В результате содержимое каталога 1 выливается в базу хранилища А.

    git filter-branch --subdirectory-filter <directory> -- --all
    # eg. git filter-branch --subdirectory-filter subfolder1/subfolder2/FOLDER_TO_KEEP -- --all
    
  5. Только для перемещения одного файла: пройдите через то, что осталось, и удалите все, кроме нужного файла. (Вам может понадобиться удалить файлы, которые вы не хотите, с тем же именем и зафиксировать.)

    git filter-branch -f --index-filter \
    'git ls-files -s | grep $'\t'FILE_TO_KEEP$ |
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
    git update-index --index-info && \
    mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE || echo "Nothing to do"' --prune-empty -- --all
    # eg. FILE_TO_KEEP = pom.xml to keep only the pom.xml file from FOLDER_TO_KEEP
    

Второй этап

  1. Шаг очистки

    git reset --hard
    
  2. Шаг очистки

    git gc --aggressive
    
  3. Шаг очистки

    git prune
    

Вы можете импортировать эти файлы в хранилище B в каталоге, а не в корне:

  1. Сделать этот каталог

    mkdir <base directory>             eg. mkdir FOLDER_TO_KEEP
    
  2. Переместить файлы в этот каталог

    git mv * <base directory>          eg. git mv * FOLDER_TO_KEEP
    
  3. Добавить файлы в этот каталог

    git add .
    
  4. Зафиксируйте ваши изменения и были готовы объединить эти файлы в новый репозиторий

    git commit
    

Этап третий

  1. Сделайте копию хранилища B, если у вас ее еще нет

    git clone <git repository B url>
    # eg. git clone https://[email protected]/scm/projects/FOLDER_TO_KEEP.git
    

    (при условии, что FOLDER_TO_KEEP - это имя нового репозитория, в который вы копируете)

  2. CD в это

    cd <git repository B directory>
    #  eg. cd /c/Working/GIT/FOLDER_TO_KEEP
    
  3. Создайте удаленное соединение с хранилищем A как ветвь в хранилище B

    git remote add repo-A-branch <git repository A directory>
    # (repo-A-branch can be anything - it just an arbitrary name)
    
    # eg. git remote add repo-A-branch /c/Working/GIT/myprojects
    
  4. Извлеките эту ветку (содержащую только каталог, который вы хотите переместить) в хранилище B.

    git pull repo-A-branch master --allow-unrelated-histories
    

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

  5. Наконец, вы, вероятно, хотите немного очиститься, удалив удаленное соединение с хранилищем A

    git remote rm repo-A-branch
    
  6. Нажмите и вы все готово.

    git push
    

Ответ 4

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

Он содержит только три шага (скопировано из блога):

# Setup a directory to hold the patches
mkdir <patch-directory>

# Create the patches
git format-patch -o <patch-directory> --root /path/to/copy

# Apply the patches in the new repo using a 3 way merge in case of conflicts
# (merges from the other repo are not turned into patches). 
# The 3way can be omitted.
git am --3way <patch-directory>/*.patch

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

git am --3way <patch-directory>/*.patch

Под Windows я получил ошибку InvalidArgument. Поэтому мне пришлось применять все патчи один за другим.

Ответ 5

СОХРАНЕНИЕ ИМЯ СПИСКА

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

Моим решением было использовать древовидный фильтр и просто удалить ненужные файлы и каталоги из временного клонирования исходного репозитория, а затем вытащить из этого клона в мой целевой репозиторий за 5 простых шагов.

# 1. clone the source
git clone ssh://<user>@<source-repo url>
cd <source-repo>
# 2. remove the stuff we want to exclude
git filter-branch --tree-filter "rm -rf <files to exclude>" --prune-empty HEAD
# 3. move to target repo and create a merge branch (for safety)
cd <path to target-repo>
git checkout -b <merge branch>
# 4. Add the source-repo as remote 
git remote add source-repo <path to source-repo>
# 5. fetch it
git pull source-repo master
# 6. check that you got it right (better safe than sorry, right?)
gitk

Ответ 6

В этом ответе представлены интересные команды на основе git am и представлены с использованием примеров, шаг за шагом.

Цель

  • Вы хотите переместить некоторые или все файлы из одного репозитория в другой.
  • Вы хотите сохранить свою историю.
  • Но вы не заботитесь о сохранении тегов и ветвей.
  • Вы принимаете ограниченную историю переименованных файлов (и файлов в переименованных каталогах).

Процедура

  • Извлечь историю в формате электронной почты, используя git log --pretty=email -p --reverse --full-index --binary
  • Реорганизовать дерево файлов и изменить имя файла в истории [необязательно]
  • Применить новую историю с помощью git am

1. Извлечение истории в формате электронной почты

Пример. Извлеките историю file3, file4 и file5

my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7

Очистить временную папку

export historydir=/tmp/mail/dir  # Absolute path
rm -rf "$historydir"             # Caution when cleaning

Очистите источник репо

git commit ...           # Commit your working files
rm .gitignore            # Disable gitignore
git clean -n             # Simulate removal
git clean -f             # Remove untracked file
git checkout .gitignore  # Restore gitignore

Извлечь историю каждого файла в формате электронной почты

cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'

К сожалению, параметр --follow или --find-copies-harder нельзя комбинировать с --reverse. Вот почему история вырезается, когда файл переименовывается (или когда родительский каталог переименовывается).

После: временная история в формате электронной почты

/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5

2. Реорганизовать дерево файлов и изменить имя файла в истории [необязательно]

Предположим, вы хотите переместить эти три файла в этом другом репо (может быть такое же репо).

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # was subdir
│   │   ├── file33    # was file3
│   │   └── file44    # was file4
│   └── dirB2         # new dir
│        └── file5    # = file5
└── dirH
    └── file77

Поэтому реорганизуйте свои файлы:

cd /tmp/mail/dir
mkdir     dirB
mv subdir dirB/dirB1
mv dirB/dirB1/file3 dirB/dirB1/file33
mv dirB/dirB1/file4 dirB/dirB1/file44
mkdir    dirB/dirB2
mv file5 dirB/dirB2

Ваша временная история теперь:

/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5

Измените также имена файлов в истории:

cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'

Примечание.. Это переписывает историю, чтобы отобразить изменение пути и имени файла.
& ЕПРС; & ЕПРС; (т.е. изменение нового местоположения/имени в новом репо)


3. Применить новую историю

Другое ваше репо:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77

Применить фиксации из временных файлов истории:

cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am 

Теперь ваше другое репо:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB            ^
│   ├── dirB1       | New files
│   │   ├── file33  | with
│   │   └── file44  | history
│   └── dirB2       | kept
│        └── file5  v
└── dirH
    └── file77

Используйте git status, чтобы увидеть количество коммитов, готовых к нажатию: -)

Примечание.. Поскольку история была переписана для изменения пути и имени файла:
& ЕПРС; & ЕПРС; (т.е. по сравнению с местоположением/именем в предыдущем репо)

  • Не нужно git mv изменять местоположение/имя файла.
  • Не нужно git log --follow для доступа к полной истории.

Дополнительный трюк: обнаружение переименованных/перемещенных файлов в вашем репо

Чтобы перечислить файлы, которые были переименованы:

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'

Дополнительные настройки: вы можете выполнить команду git log с помощью опций --find-copies-harder или --reverse. Вы также можете удалить первые два столбца с помощью cut -f3- и grepping complete pattern '{. * = > . *}'.

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'

Ответ 7

Я всегда использую http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/. Простой и быстрый.

Для соответствия стандартам stackoverflow, выполните следующие действия:

mkdir /tmp/mergepatchs
cd ~/repo/org
export reposrc=myfile.c #or mydir
git format-patch -o /tmp/mergepatchs $(git log $reposrc|grep ^commit|tail -1|awk '{print $2}')^..HEAD $reposrc
cd ~/repo/dest
git am /tmp/mergepatchs/*.patch

Ответ 8

Имея аналогичный зуд для царапин (хотя и для некоторых файлов данного репозитория), этот script оказался действительно полезным: git-import

Короткий вариант состоит в том, что он создает файлы исправлений данного файла или каталога ($object) из существующего репозитория:

cd old_repo
git format-patch --thread -o "$temp" --root -- "$object"

которые затем применяются к новому репозиторию:

cd new_repo
git am "$temp"/*.patch 

Подробнее см.

Ответ 9

Попробуй это

cd repo1

Это удалит все каталоги, кроме упомянутых, сохраняя историю только для этих каталогов.

git filter-branch --index-filter 'git rm --ignore-unmatch --cached -qr -- . && git reset -q $GIT_COMMIT -- dir1/ dir2/ dir3/ ' --prune-empty -- --all

Теперь вы можете добавить свой новый репозиторий в свой git remote и добавить его к этому

git remote remove origin <old-repo>
git remote add origin <new-repo>
git push origin <current-branch>

добавить -f для перезаписи

Ответ 10

Используя вдохновение из http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/, я создал эту функцию Powershell для того, чтобы сделать то же самое, что до сих пор отлично работало для меня:

# Migrates the git history of a file or directory from one Git repo to another.
# Start in the root directory of the source repo.
# Also, before running this, I recommended that $destRepoDir be on a new branch that the history will be migrated to.
# Inspired by: http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/
function Migrate-GitHistory
{
    # The file or directory within the current Git repo to migrate.
    param([string] $fileOrDir)
    # Path to the destination repo
    param([string] $destRepoDir)
    # A temp directory to use for storing the patch file (optional)
    param([string] $tempDir = "\temp\migrateGit")

    mkdir $tempDir

    # git log $fileOrDir -- to list commits that will be migrated
    Write-Host "Generating patch files for the history of $fileOrDir ..." -ForegroundColor Cyan
    git format-patch -o $tempDir --root -- $fileOrDir

    cd $destRepoDir
    Write-Host "Applying patch files to restore the history of $fileOrDir ..." -ForegroundColor Cyan
    ls $tempDir -Filter *.patch  `
        | foreach { git am $_.FullName }
}

Использование для этого примера:

git clone project2
git clone project1
cd project1
# Create a new branch to migrate to
git checkout -b migrate-from-project2
cd ..\project2
Migrate-GitHistory "deeply\buried\java\source\directory\A" "..\project1"

После этого вы можете перенастроить файлы в ветке migrate-from-project2 до слияния.

Ответ 11

Я хотел что-то надежное и многоразовое (одна-команда-и-go + функция отмены), поэтому я написал следующее bash script. Работал для меня несколько раз, поэтому я подумал, что поделюсь им здесь.

Он может перемещать произвольную папку /path/to/foo из repo1 в /some/other/folder/bar в repo2 (пути к папкам могут быть одинаковыми или разными, расстояние от корневой папки может быть разным).

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

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

Если нет конфликтов имен файлов, вам просто нужно git commit в конце, чтобы завершить слияние.

Недостатком является то, что он, скорее всего, не будет следовать переименованиям файлов (за пределами REWRITE_FROM) в исходном репо - запросы на перенос приветствуются в GitHub для размещения для этого.

Ссылка GitHub: git-move-folder-between-repos-keep-history

#!/bin/bash

# Copy a folder from one git repo to another git repo,
# preserving full history of the folder.

SRC_GIT_REPO='/d/git-experimental/your-old-webapp'
DST_GIT_REPO='/d/git-experimental/your-new-webapp'
SRC_BRANCH_NAME='master'
DST_BRANCH_NAME='import-stuff-from-old-webapp'
# Most likely you want the REWRITE_FROM and REWRITE_TO to have a trailing slash!
REWRITE_FROM='app/src/main/static/'
REWRITE_TO='app/src/main/static/'

verifyPreconditions() {
    #echo 'Checking if SRC_GIT_REPO is a git repo...' &&
      { test -d "${SRC_GIT_REPO}/.git" || { echo "Fatal: SRC_GIT_REPO is not a git repo"; exit; } } &&
    #echo 'Checking if DST_GIT_REPO is a git repo...' &&
      { test -d "${DST_GIT_REPO}/.git" || { echo "Fatal: DST_GIT_REPO is not a git repo"; exit; } } &&
    #echo 'Checking if REWRITE_FROM is not empty...' &&
      { test -n "${REWRITE_FROM}" || { echo "Fatal: REWRITE_FROM is empty"; exit; } } &&
    #echo 'Checking if REWRITE_TO is not empty...' &&
      { test -n "${REWRITE_TO}" || { echo "Fatal: REWRITE_TO is empty"; exit; } } &&
    #echo 'Checking if REWRITE_FROM folder exists in SRC_GIT_REPO' &&
      { test -d "${SRC_GIT_REPO}/${REWRITE_FROM}" || { echo "Fatal: REWRITE_FROM does not exist inside SRC_GIT_REPO"; exit; } } &&
    #echo 'Checking if SRC_GIT_REPO has a branch SRC_BRANCH_NAME' &&
      { cd "${SRC_GIT_REPO}"; git rev-parse --verify "${SRC_BRANCH_NAME}" || { echo "Fatal: SRC_BRANCH_NAME does not exist inside SRC_GIT_REPO"; exit; } } &&
    #echo 'Checking if DST_GIT_REPO has a branch DST_BRANCH_NAME' &&
      { cd "${DST_GIT_REPO}"; git rev-parse --verify "${DST_BRANCH_NAME}" || { echo "Fatal: DST_BRANCH_NAME does not exist inside DST_GIT_REPO"; exit; } } &&
    echo '[OK] All preconditions met'
}

# Import folder from one git repo to another git repo, including full history.
#
# Internally, it rewrites the history of the src repo (by creating
# a temporary orphaned branch; isolating all the files from REWRITE_FROM path
# to the root of the repo, commit by commit; and rewriting them again
# to the original path).
#
# Then it creates another temporary branch in the dest repo,
# fetches the commits from the rewritten src repo, and does a merge.
#
# Before any work is done, all the preconditions are verified: all folders
# and branches must exist (except REWRITE_TO folder in dest repo, which
# can exist, but does not have to).
#
# The code should work reasonably on repos with reasonable git history.
# I did not test pathological cases, like folder being created, deleted,
# created again etc. but probably it will work fine in that case too.
#
# In case you realize something went wrong, you should be able to reverse
# the changes by calling `undoImportFolderFromAnotherGitRepo` function.
# However, to be safe, please back up your repos just in case, before running
# the script. `git filter-branch` is a powerful but dangerous command.
importFolderFromAnotherGitRepo(){
    SED_COMMAND='s-\t\"*-\t'${REWRITE_TO}'-'

    verifyPreconditions &&
    cd "${SRC_GIT_REPO}" &&
      echo "Current working directory: ${SRC_GIT_REPO}" &&
      git checkout "${SRC_BRANCH_NAME}" &&
      echo 'Backing up current branch as FILTER_BRANCH_BACKUP' &&
      git branch -f FILTER_BRANCH_BACKUP &&
      SRC_BRANCH_NAME_EXPORTED="${SRC_BRANCH_NAME}-exported" &&
      echo "Creating temporary branch '${SRC_BRANCH_NAME_EXPORTED}'..." &&
      git checkout -b "${SRC_BRANCH_NAME_EXPORTED}" &&
      echo 'Rewriting history, step 1/2...' &&
      git filter-branch -f --prune-empty --subdirectory-filter ${REWRITE_FROM} &&
      echo 'Rewriting history, step 2/2...' &&
      git filter-branch -f --index-filter \
       "git ls-files -s | sed \"$SED_COMMAND\" |
        GIT_INDEX_FILE=\$GIT_INDEX_FILE.new git update-index --index-info &&
        mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" HEAD &&
    cd - &&
    cd "${DST_GIT_REPO}" &&
      echo "Current working directory: ${DST_GIT_REPO}" &&
      echo "Adding git remote pointing to SRC_GIT_REPO..." &&
      git remote add old-repo ${SRC_GIT_REPO} &&
      echo "Fetching from SRC_GIT_REPO..." &&
      git fetch old-repo "${SRC_BRANCH_NAME_EXPORTED}" &&
      echo "Checking out DST_BRANCH_NAME..." &&
      git checkout "${DST_BRANCH_NAME}" &&
      echo "Merging SRC_GIT_REPO/" &&
      git merge "old-repo/${SRC_BRANCH_NAME}-exported" --no-commit &&
    cd -
}

# If something didn't work as you'd expect, you can undo, tune the params, and try again
undoImportFolderFromAnotherGitRepo(){
  cd "${SRC_GIT_REPO}" &&
    SRC_BRANCH_NAME_EXPORTED="${SRC_BRANCH_NAME}-exported" &&
    git checkout "${SRC_BRANCH_NAME}" &&
    git branch -D "${SRC_BRANCH_NAME_EXPORTED}" &&
  cd - &&
  cd "${DST_GIT_REPO}" &&
    git remote rm old-repo &&
    git merge --abort
  cd -
}

importFolderFromAnotherGitRepo
#undoImportFolderFromAnotherGitRepo

Ответ 12

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

#Source directory
git remote rm origin
#Target directory
git remote add branch-name-from-old-repo ../source_directory

В этих двух шагах я смог заставить другую ветку репо появиться в том же репо.

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

git br --set-upstream-to=origin/mainline

Теперь он вел себя так: если бы это была просто еще одна ветка, я толкнул ее против того же репо.

Ответ 13

Если пути для файлов, о которых идет речь, одинаковы в двух репозиториях, и вы хотите перенести только один файл или небольшой набор связанных файлов, один простой способ сделать это - использовать git cherry-pick.

Первым шагом является передача коммитов из другого репо в ваше собственное локальное репо с помощью git fetch <remote-url>. Это приведет к тому, что FETCH_HEAD укажет на фиксацию головы из другого репо; если вы хотите сохранить ссылку на эту фиксацию после того, как вы сделали другие выборки, вы можете пометить ее с помощью git tag other-head FETCH_HEAD.

Затем вам нужно будет создать начальную фиксацию для этого файла (если она не существует) или фиксация, чтобы привести файл в состояние, которое может быть исправлено с первым фиксацией из другого репо, которое вы хотите ввести. вы можете сделать это с помощью git cherry-pick <commit-0> если commit-0 представил нужные вам файлы, или вам может понадобиться построить commit "вручную". Добавьте -n к вариантам вишневого выбора, если вам нужно изменить первоначальную фиксацию, например, удалить файлы из этого коммита, который вы не хотите вводить.

После этого вы можете продолжать git cherry-pick последующие коммиты, используя снова -n где это необходимо. В простейшем случае (все коммиты - это именно то, что вы хотите и применяете чисто), вы можете дать полный список git cherry-pick <commit-1> <commit-2> <commit-3>... командной строке git cherry-pick <commit-1> <commit-2> <commit-3>...: git cherry-pick <commit-1> <commit-2> <commit-3>...

Ответ 14

Приведенный ниже метод переноса моего GIT Stash в GitLab с сохранением всех веток и сохранением истории.

Клонировать старый репозиторий на локальный.

git clone --bare <STASH-URL>

Создайте пустой репозиторий в GitLab.

git push --mirror <GitLab-URL>

Выше я выполнил, когда мы перенесли наш код из stash в GitLab, и он работал очень хорошо.