繁体   English   中英

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

[英]How to move some files from one git repo to another (not a clone), preserving history

我们的 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 -- 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 -- path/to/file_or_folder | (cd /path/to/new_repository && git am --committer-date-is-author-date)

(取自Exherbo 的文档

尝试了各种方法将文件或文件夹从一个 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://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

第二阶段

  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,请复制存储库 B

     git clone <git repository B url> # eg. git clone https://username@giturl/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'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

是的,点击filter-branch--subdirectory-filter是关键。 您使用它的事实基本上证明没有更简单的方法 - 您别无选择,只能重写历史记录,因为您希望最终只得到文件的(重命名)子集​​,而这根据定义会更改哈希值。 由于没有任何标准命令(例如pull )重写历史记录,因此您无法使用它们来完成此操作。

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

我发现Ross Hendrickson 的博客非常有用。 这是一种非常简单的方法,您可以在其中创建应用于新存储库的补丁。 有关更多详细信息,请参阅链接页面。

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

# 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 错误。 所以我不得不一个接一个地应用所有补丁。

这通过使用 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

保留目录名称

子目录过滤器(或更短的命令 git subtree)效果很好,但对我不起作用,因为它们从提交信息中删除了目录名称。 在我的场景中,我只想将一个存储库的一部分合并到另一个存储库中,并保留带有完整路径名的历史记录。

我的解决方案是使用树过滤器并简单地从源存储库的临时克隆中删除不需要的文件和目录,然后通过 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

我经常使用的是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

有类似的痒痒(尽管仅适用于给定存储库的某些文件),这个脚本被证明非常有用: 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 am的有趣命令,并使用示例一步一步地呈现。

客观的

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

程序

  1. 使用电子邮件格式提取历史记录
    git log --pretty=email -p --reverse --full-index --binary
  2. 重新组织文件树并更新历史记录中的文件名更改 [可选]
  3. 使用git am应用新的历史记录

1.以电子邮件格式提取历史记录

示例:提取file3file4file5的历史记录

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)。

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查看准备推送的提交数量 :-)

注意:由于历史记录已被重写以反映路径和文件名的更改:
(即与上一个 repo 中的位置/名称相比)

  • 无需git mv即可更改位置/文件名。
  • 无需git log --follow即可访问完整历史记录。

额外技巧:在你的仓库中检测重命名/移动的文件

要列出已重命名的文件:

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

更多自定义:您可以使用选项--find-copies-harder harder 或--reverse完成命令git log 您还可以使用cut -f3-和 grepping 完整模式 '{.* => .*}' 删除前两列。

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

尝试这个

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 遥控器中添加您的新仓库并将其推送到该仓库

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

添加-f覆盖

使用来自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分支上的文件。

我想要一些健壮且可重用的东西(一个命令并执行 + 撤消功能),所以我编写了以下 bash 脚本。 多次为我工作,所以我想我会在这里分享。

它能够将任意文件夹/path/to/foorepo1/some/other/folder/barrepo2 (文件夹路径可以相同或不同,与根文件夹的距离可能不同)。

由于它只检查涉及输入文件夹中文件的提交(而不是源存储库的所有提交),因此即使在大型源存储库中也应该非常快,如果您只是提取一个在每个文件中都没有触及的深层嵌套子文件夹犯罪。

因为这样做是用所有旧仓库的历史创建一个孤立的分支,然后将它合并到 HEAD,它甚至可以在文件名冲突的情况下工作(然后你必须在最后解决合并) .

如果没有文件名冲突,您只需要最后git commit即可完成合并。

缺点是它可能不会跟随源 repo 中的文件重命名(在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

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

就我而言,我不需要保留要从中迁移的存储库或保留任何以前的历史记录。 我有一个相同分支的补丁,来自不同的遥控器

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

在这两个步骤中,我能够让另一个 repo 的分支出现在同一个 repo 中。

最后,我设置了这个分支(我从另一个仓库导入的)跟随目标仓库的主线(这样我就可以准确地区分它们)

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

现在它表现得好像它只是我针对同一个 repo 推送的另一个分支。

如果两个存储库中相关文件的路径相同,并且您只想带入一个文件或一小组相关文件,那么一种简单的方法是使用git cherry-pick

第一步是使用git fetch <remote-url>将来自其他 repo 的提交带入您自己的本地 repo。 这将使FETCH_HEAD指向另一个仓库的头部提交; 如果您想在完成其他提取后保留对该提交的引用,您可能需要使用git tag other-head FETCH_HEAD对其进行标记。

然后,您将需要为该文件创建一个初始提交(如果它不存在)或一个提交以使该文件进入一个可以使用您想要引入的其他存储库的第一个提交进行修补的状态。您可以如果commit-0引入了您想要的文件,则可以使用git cherry-pick <commit-0>执行此操作,或者您可能需要“手动”构建提交。 如果您需要修改初始提交,例如,从该提交中删除您不想引入的文件,请将-n添加到cherry-pick 选项中。

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

我做了什么:

  1. 将存储库克隆到文件夹
  2. cd 现有项目
  3. 在这里打开一个 git 终端
  4. git remote set-url origin <NEW_GIT_URL>
  5. git push -u origin --all
  6. git push origin --tags

不需要 linux 或 Github 命令

1)在线访问github。 2)使用您要移动的文件转到旧存储库。 3)原始文件内容复制。 我的是 PytorchImageSegmentation.ipynb 4)创建新存储库并输入它 5)单击添加新文件,并创建新文件 6)将内容粘贴到文件中 7)赋予文件与其他存储库相同的扩展名。 我的 was.ipynb 和我保持相同的标题,所以在新的 repo 中它也是 PytorchImageSegmentation.ipynb。

文件已移动。 没有尝试过文件夹。 我不认为这是可能的。

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

将旧存储库克隆到本地。

git clone --bare <STASH-URL>

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

git push --mirror <GitLab-URL>

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM