代码之家  ›  专栏  ›  技术社区  ›  ebneter

如何将文件从一个git repo移动到另一个git repo(而不是克隆),从而保留历史记录

  •  408
  • ebneter  · 技术社区  · 17 年前

    我们的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
    

    但这似乎相当复杂。一般来说,有没有更好的方法来做这类事情?还是我采取了正确的方法?

    请注意,这涉及将历史记录合并到现有存储库中,而不是简单地从另一个存储库的一部分创建一个新的独立存储库( as in an earlier question ).

    13 回复  |  直到 5 年前
        1
  •  329
  •   weakish    6 年前

    如果您的历史记录正常,您可以将提交作为补丁取出,并将其应用于新存储库:

    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’s docs

        2
  •  81
  •   wass rubleff orgoj    7 年前

    在尝试了各种方法将文件或文件夹从一个Git存储库移动到另一个存储库后,下面列出了唯一一种似乎可靠的方法。

    它涉及克隆要从中移动文件或文件夹的存储库,将该文件或文件夹移动到根目录,重写Git历史记录,克隆目标存储库,并将具有历史记录的文件或文件夹直接拉入此目标存储库。

    第一阶段

    1. 您不应该推送此副本的更改!

      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. 浏览您的历史记录和文件,删除任何不在其中的内容 进入存储库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
      

    第二阶段

    1. 清除步骤

      git reset --hard
      
    2. 清除步骤

      git gc --aggressive
      
    3. 清除步骤

      git prune
      

    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://username@giturl/scm/projects/FOLDER_TO_KEEP.git
      

    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
      
        3
  •  61
  •   StackzOfZtuff    11 年前

    是的,点击 --subdirectory-filter 的 filter-branch 是关键。你使用它的事实基本上证明了没有更简单的方法——你别无选择,只能重写历史记录,因为你只想得到文件的一个子集(重命名),而这从定义上改变了哈希值。由于没有标准命令(例如。 pull )重写历史,你不可能用它们来实现这一点。

    当然,你可以细化细节——你的一些克隆和分支并不是绝对必要的——但总体方法是好的!遗憾的是,它很复杂,但当然,git的目的不是让重写历史变得容易。

        4
  •  23
  •   darthbith    8 年前

    通过使用git过滤器仓库,这变得更加简单。

    为了移动 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 more details and options in README )

    # Before: (root)
    .
    |-- project1
    |   `-- 3
    `-- project2
        |-- 1
        `-- sub
            `-- dir
                `-- 2
    
    # After: (project1)
    .
    ├── 3
    └── sub
        └── dir
            └── 2
    
        5
  •  11
  •   codeMonkey    5 年前

    我发现了 Ross Hendrickson's blog 非常有用。这是一种非常简单的方法,您可以创建应用于新仓库的补丁。有关更多详细信息,请参阅链接页面。

    它只包含三个步骤(从博客复制):

    # 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
    

        6
  •  9
  •   Hugh Perkins    9 年前

    我经常用的就是这里 http://blog.neutrino.es/2012/git-copy-a-file-or-directory-from-another-repository-preserving-history/

    为了符合堆栈溢出标准,以下是程序:

    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
    
        7
  •  8
  •   Jocce Nilsson    11 年前

    保留目录名

    子目录过滤器(或更短的命令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
    
        8
  •  5
  •   oHo Denis Tulskiy    10 年前

    git-import

    简而言之,它创建给定文件或目录的补丁文件( $object )从现有存储库中:

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

    然后将其应用于新的存储库:

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

    (来自另一位作者)以下人员可以使用这种有用的方法 。以下是一个示例用法:

    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
    }
    
        9
  •  5
  •   WestCoastProjects    5 年前

    git subtree 作品直观,甚至保存了历史。

    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
    
        10
  •  2
  •   Chetan Basutkar    7 年前

    此答案基于以下内容提供了有趣的命令 git am

    目标

    • 您希望将部分或所有文件从一个存储库移动到另一个存储库。
    • 你想保留他们的历史。
    • 但你不在乎保留标签和树枝。
    • 您接受重命名文件(以及重命名目录中的文件)的有限历史记录。

    程序

    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
    

    清理你的仓库 来源

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

    注: 这将重写历史记录以反映路径和文件名的更改。
    (即新回购中新位置/名称的更改)


    您的另一个repo是:

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

    应用临时历史文件中的提交:

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

    您的另一个repo现在是:

    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 使用选项 或 --反向 。您还可以使用以下命令删除前两列 cut -f3- 并对完整模式“{.*=>.*}”进行grepping。

    find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'
    
        11
  •  1
  •   crimbo    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 在合并之前先进行分支。

        12
  •  1
  •   jakub.g    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中添加新的repo并将其推送到该位置

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

    -f 覆盖

        13
  •  0
  •   Jason D    8 年前

    我想要一些健壮且可重用的东西(一个命令和go+undo函数),所以我编写了以下bash脚本。曾为我工作过几次,所以我想在这里分享一下。

    它能够移动任意文件夹 /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
    
        14
  •  0
  •   cjs    8 年前

    就我而言,我不需要保留我正在迁移的仓库,也不需要保留任何以前的历史。我有一块同样的树枝,来自不同的遥控器

    #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
    

    现在,它的行为就像是我反对同一回购的另一个分支。

        15
  •  0
  •   Tamás Lévai    5 年前

    git cherry-pick .

    第一步是使用 git fetch <remote-url> FETCH_HEAD git tag other-head FETCH_HEAD .

    然后,您需要为该文件创建一个初始提交(如果它不存在),或者创建一个提交,使文件处于可以用您想要引入的其他仓库中的第一个提交修补的状态。您可以使用 git cherry-pick <commit-0> 如果 commit-0 -n 如果您需要修改初始提交,例如从该提交中删除您不想引入的文件,请使用樱桃选择选项。

    之后,您可以继续 后续提交,再次使用 n 必要时。在最简单的情况下(所有提交都是你想要的,并且应用得很干净),你可以在cherry pick命令行上给出完整的提交列表: git cherry-pick <commit-1> <commit-2> <commit-3> ... .

        16
  •  -2
  •   Roopkumar Akubathini    7 年前

    下面的方法通过维护所有分支和保留历史记录将我的GIT Stash迁移到GitLab。

    将旧存储库克隆到本地。

    git clone --bare <STASH-URL>
    

    在GitLab中创建一个空存储库。

    git push --mirror <GitLab-URL>
    

    当我们将代码从stash迁移到GitLab时,我执行了上述操作,效果非常好。