programing

어떤 git repo에서 (복제가 아닌) 다른 git repo로 일부 파일을 이동하는 방법

megabox 2023. 4. 9. 21:18
반응형

어떤 git repo에서 (복제가 아닌) 다른 git repo로 일부 파일을 이동하는 방법

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 overwrite 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

하지만 그것은 꽤 복잡해 보인다.일반적으로 이런 일을 할 수 있는 더 좋은 방법이 있을까요?아니면 제가 올바른 접근법을 채택했나요?

작업에는 이전 질문에서와 같이 단순히 다른 독립 실행형 리포지토리의 일부에서 새 독립 실행형 리포지토리를 생성하는 것이 아니라 기존 리포지토리에 이력을 병합하는 작업이 포함됩니다.

이력이 정상인 경우 커밋을 패치로 꺼내 새 저장소에 적용할 수 있습니다.

cd repository
git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- path/to/file_or_folder > patch
cd ../another_repository
git am --committer-date-is-author-date < ../repository/patch 

또는 한 줄로

git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- path/to/file_or_folder | (cd /path/to/new_repository && git am --committer-date-is-author-date)

루트 디렉토리에 경우: " " " " " " " " " " " 。 " " " "git am 수 있다-p2이치노

(Exherbo의 문서에서 인용)

Git 저장소에서 다른 저장소로 파일이나 폴더를 이동하기 위해 다양한 방법을 시도해 본 결과, 유일하게 안정적으로 작동하는 것으로 보이는 방법이 아래에 나와 있습니다.

파일 또는 폴더를 이동하려는 저장소 복제, 파일 또는 폴더 루트 이동, Git 기록 다시 쓰기, 대상 저장소 복제 및 이력이 있는 파일 또는 폴더를 이 대상 저장소로 직접 꺼내는 작업이 포함됩니다.

스테이지 1

  1. 다음 단계에서는 푸시하지 않아야 하는 이 복사본에 대한 주요 변경을 수행하므로 저장소 A의 복사본을 만드십시오.

    git clone --branch <branch> --origin origin --progress \
      -v <git repository A url>
    # eg. git clone --branch master --origin origin --progress \
    #   -v https://username@giturl/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 의 컨텐츠가 저장소 A 의 베이스에 분출됩니다.

    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
    

스테이지 2

  1. 정리 단계

    git reset --hard
    
  2. 정리 단계

    git gc --aggressive
    
  3. 정리 단계

    git prune
    

다음 파일을 루트가 아닌 디렉토리 내의 저장소 B로 Import할 수 있습니다.

  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
    

스테이지 3

  1. 저장소 B가 없는 경우 복사본을 만듭니다.

    git clone <git repository B url>
    # eg. git clone https://username@giturl/scm/projects/FOLDER_TO_KEEP.git
    

    (폴더로 상정)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's 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
    

, ★★★★★★★★★★★★★★★★★★★★★★★★★★.--subdirectory-filterfilter-branch핵심이었습니다.이 파일을 사용했다는 것은 기본적으로 쉬운 방법이 없다는 것을 증명합니다.파일의 서브셋(이름 변경)만을 사용하고 싶었기 때문에 이력을 다시 쓸 수밖에 없었습니다.이치노표준 명령어가 없기 때문입니다(예:pull 쓰는 것은 이력을재작성합니다.이것을실행하는데사용할수있는방법이없습니다.

물론 클로닝과 브랜칭이 엄격히 필요하지 않은 경우도 있지만 전체적인 접근법은 훌륭합니다.복잡한 것은 유감이지만, 물론 git의 목적은 역사를 쉽게 고쳐 쓰는 것이 아닙니다.

이것은 git-filter-repo를 사용하면 간단해집니다.

「 「 」를 이동하기 project2/sub/dir로로 합니다.project1/sub/dir:

# Create a new repo containing only the subdirectory:
git clone project2 project2_clone --no-local
cd project2_clone
git filter-repo --path sub/dir

# Merge the new repo:
cd ../project1
git remote add tmp ../project2_clone/
git fetch tmp master
git merge remotes/tmp/master --allow-unrelated-histories
git remote remove tmp

말하면, 이 할 수 있습니다: 툴을 、 음음 、 음음 、 음음 。pip3 install git-filter-repo(README 상세옵션)

# Before: (root)
.
|-- project1
|   `-- 3
`-- project2
    |-- 1
    `-- sub
        `-- dir
            `-- 2

# After: (project1)
.
├── 3
└── sub
    └── dir
        └── 2

나는 로스 헨드릭슨의 블로그가 매우 유용하다는 것을 알았다.이는 새로운 리포에 적용할 패치를 작성하는 매우 간단한 방법입니다.자세한 내용은 링크된 페이지를 참조하십시오.

3단계(블로그에서 복사)만 포함되어 있습니다.

# 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 오류가 발생하였습니다.그래서 저는 모든 패치를 하나씩 적용해야만 했습니다.

항상 사용하는 것은 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

디렉토리 이름 유지

subdirectory-filter(또는 짧은 명령어 git 서브트리)는 정상적으로 동작하지만 커밋 정보에서 디렉토리 이름을 삭제하기 때문에 나에게는 동작하지 않습니다.이 시나리오에서는 한 저장소의 일부를 다른 저장소로 병합하고 전체 경로 이름으로 이력을 유지하려고 합니다.

이 솔루션은 트리 필터를 사용하여 소스 저장소의 임시 클론에서 불필요한 파일 및 디렉토리를 삭제한 후 해당 클론에서 타깃 저장소로 간단하게 풀하는 것입니다.

# 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

스크래치(특정 저장소의 일부 파일에만 해당)에 대한 비슷한 가려움증이 있었기 때문에 이 스크립트는 매우 도움이 되었습니다: git-import

, 입니다( 「」 「」 「」 「」 「」 「」).$object를) 사용할 수 있습니다.

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

그런 다음 새 저장소에 적용됩니다.

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

자세한 내용은 다음을 참조하십시오.

업데이트(다른 작성자로부터)이 유용한 접근법은 다음 bash 함수에 의해 사용될 수 있습니다.다음은 사용 예를 제시하겠습니다.

gitcp <Repo1_basedir> <path_inside_repo1> <Repo2_basedir>

gitcp ()
{
    fromdir="$1";
    frompath="$2";
    to="$3";
    echo "Moving git files from "$fromdir" at "$frompath" to "$to" ..";
    tmpdir=/tmp/gittmp;
    cd "$fromdir";
    git format-patch --thread -o $tmpdir --root -- "$frompath";
    cd "$to";
    git am $tmpdir/*.patch
}

git subtree 직관적으로 작동하며 역사를 보존할 수 있습니다.

사용 예:git repo를 서브디렉토리로 추가합니다.

git subtree add --prefix foo https://github.com/git/git.git master

설명:

#├── repo_bar
#│   ├── bar.txt
#└── repo_foo
#    └── foo.txt

cd repo_bar
git subtree add --prefix foo ../repo_foo master

#├── repo_bar
#│   ├── bar.txt
#│   └── foo
#│       └── foo.txt
#└── repo_foo
#    └── foo.txt

이 답변은 예시를 기반으로 한 흥미로운 명령어를 단계별로 제공합니다.

객관적으로

  • 일부 또는 모든 파일을 한 저장소에서 다른 저장소로 이동하려고 합니다.
  • 그들의 역사를 간직하고 싶군요
  • 그러나 태그와 브랜치를 유지하는 것은 신경 쓰지 않습니다.
  • 이름이 변경된 파일(및 이름이 변경된 디렉토리의 파일)에 대해 제한된 이력을 허용합니다.

절차.

  1. 을 이메일 하려면 을 합니다.
    git log --pretty=email -p --reverse --full-index --binary
  2. 파일 트리 재구성 및 기록 파일 이름 변경 업데이트 [옵션]
  3. 사용하여 새로운 을 적용합니다.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

repo 소스를 청소합니다.

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. 파일 트리 재구성 및 이력 파일 이름 변경 갱신 [옵션]

이 다른 repo(같은 repo일 수도 있음)에서 이들 3개의 파일을 이동한다고 가정합니다.

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"' {} ';'

주의: 경로 및 파일 이름 변경을 반영하여 이력을 다시 씁니다.
      ( 장소 (예: 새로운 repo 내의 새로운 장소/이름 변경) (예: 새로운 repo 내의 새로운 장소/이름 변경


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을 확인하려면를 선택합니다.

주의: 이력은 경로 및 파일 이름 변경을 반영하도록 다시 작성되었습니다.
      )(예: 이전 repo내의 위치/과 비교)

  • ""는 필요 .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-이치노* = > .*}'

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

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마지 마지

이거 드셔보세요

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 리모콘에 새로운 repo를 추가하여 거기에 푸시할 수 있습니다.

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

-f

견고하고 재사용 가능한 기능(원커맨드 앤 고 + 실행 취소 기능)을 원했기 때문에, 이하의 bash 스크립트를 작성했습니다.여러 번 일했으니까 여기서 공유할까 해서요

It is able to move an arbitrary folder 임의의 폴더를 이동할 수 있습니다./path/to/foo부에서repo1 into 안으로/some/other/folder/bar로로 합니다.repo2(폴더 경로가 동일하거나 루트 폴더의 거리는 다를 수 있습니다.)(폴더 경로는 같거나 다를 수 있으며 루트 폴더와의 거리는 다를 수 있습니다).

입력 폴더 내의 파일에 접촉하는 커밋만을 통과하기 때문에(소스 repo의 모든 커밋을 통과하지 않음), 모든 커밋에서 접촉하지 않은 깊이 중첩된 서브폴더를 추출하는 것만으로 큰 소스 저장소에서도 매우 빠릅니다.

이렇게 하면 오래된 repo의 모든 이력을 사용하여 고립된 분기를 만들고 이를 HEAD에 병합하는 것이므로 파일 이름이 충돌하는 경우에도 작동합니다(이 경우 마지막에 병합을 해결해야 합니다).

경합이 는, 「」 「」 「」 「」 「」 「」 「」로 하면 .git commit를 클릭하여 마지를 완료합니다.

변경( 이름 이외)이 뒤따르지 수 입니다.REWRITE_FROM【repo - pull 】【folder】【GitHub】【GitHub】【GitHub】【folderfolder】

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

이 경우 마이그레이션한 보고서를 보존하거나 이전 기록을 보존할 필요가 없었습니다.다른 리모콘에서 같은 분기의 패치를 사용하고 있었습니다.

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

그 두 단계에서 나는 다른 쪽 리포의 브랜치를 같은 리포에 표시할 수 있었다.

마지막으로 (다른 repo에서 Import한) 이 브랜치를 (정확하게 구분할 수 있도록) 타겟 repo의 메인라인을 따르도록 설정했습니다.

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

이제 그건 마치 다른 나뭇가지처럼 행동했어 내가 그 보고서에 대고 밀었던 것처럼 말이야

있는 파일의 또는 는, 「」를해 주세요.git cherry-pick.

는 다른 쪽을 자신의 입니다.git fetch <remote-url> 하면 남습니다.FETCH_HEAD commit을 한 후 하려면 ada repo로 할 수 .다른 페치를 실행한 후 해당 커밋에 대한 참조를 유지하려면 태그 붙일 수 있습니다.git tag other-head FETCH_HEAD.

그런 다음 해당 파일의 초기 커밋(존재하지 않는 경우)을 작성하거나 파일을 가져오는 다른 repo의 첫 번째 커밋으로 패치할 수 있는 상태로 커밋해야 합니다. 할 수 있어요.git cherry-pick <commit-0>commit-0이치노그렇지 않으면 커밋을 '수작업'으로 구성해야 할 수도 있습니다.-n하지 않는 커밋에서 드롭하는 등 가 있는 합니다.

다음에 '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 하다.git cherry-pick 후의, 「」를 사용합니다.-n가장(모든 에는 체리픽 명령줄의 전체 목록할 수 있습니다.git cherry-pick <commit-1> <commit-2> <commit-3> ....

아래는 모든 브랜치를 유지하고 이력을 보존함으로써 Git Stash를 GitLab으로 이행하는 방법입니다.

이전 저장소를 로컬로 복제합니다.

git clone --bare <STASH-URL>

GitLab에 빈 저장소를 만듭니다.

git push --mirror <GitLab-URL>

위의 내용은 Stash에서 GitLab으로 코드를 이행했을 때 수행했는데 매우 잘 작동했습니다.

언급URL : https://stackoverflow.com/questions/1365541/how-to-move-some-files-from-one-git-repo-to-another-not-a-clone-preserving-hi

반응형