如何将现有的Git仓库导入到另一个仓库中?

580

我有一个名为XXX的文件夹中的Git存储库,还有一个名为YYY的第二个Git存储库。

我想将XXX存储库作为名为ZZZ的子目录导入到YYY存储库中,并将所有XXX的更改历史记录添加到YYY中。

导入前的文件夹结构:

├── XXX
│   ├── .git
│   └── (project files)
└── YYY
    ├── .git
    └── (project files)

执行后的文件夹结构:

YYY
├── .git  <-- This now contains the change history from XXX
├──  ZZZ  <-- This was originally XXX
│    └── (project files)
└──  (project files)

这可行吗,还是我必须使用子模块?


2
在Github上,现在可以通过Web界面在创建新存储库时执行此操作。 - Ben G
可能是如何合并两个git仓库?的重复问题。 - BuZZ-dEE
1
@bgcode的评论对我非常有帮助 - 谢谢。你可以直接从GitHub的UI导入另一个仓库,这样可以节省大量工作。 - ChumKui
17个回答

1

请查看本文中的基本示例,并考虑在存储库上进行以下映射:

  • A <-> YYY
  • B <-> XXX

在完成本章描述的所有活动(合并后),请删除分支B-master

$ git branch -d B-master

然后,推送更改。

对我有用。


1

我想从另一个代码库(XXX)中只导入一些文件。对于我来说,子树太复杂了,其他解决方案也不起作用。这是我所做的:

ALL_COMMITS=$(git log --reverse --pretty=format:%H -- ZZZ | tr '\n' ' ')

这将为您提供一个以空格分隔的列表,其中包含所有影响我想导入的文件(ZZZ)的提交,按相反顺序排列(您可能需要添加--follow以捕获重命名)。然后我进入目标存储库(YYY),将另一个存储库(XXX)添加为远程存储库,从中进行了提取,最后执行以下操作:

git cherry-pick $ALL_COMMITS

这将把所有提交添加到您的分支中,因此您将拥有所有文件及其历史记录,并且可以像它们一直在这个存储库中一样使用它们。


0

我曾经遇到这样的情况,我正在寻找-s theirs,但是当然,这种策略并不存在。我的历史记录是,我在GitHub上fork了一个项目,现在由于某些原因,我的本地master无法与upstream/master合并,尽管我没有对此分支进行任何本地更改。(真的不知道发生了什么 - 我猜upstream在幕后做了一些不好的推送,也许?)

最终我做的是

# as per https://help.github.com/articles/syncing-a-fork/
git fetch upstream
git checkout master
git merge upstream/master
....
# Lots of conflicts, ended up just abandonging this approach
git reset --hard   # Ditch failed merge
git checkout upstream/master
# Now in detached state
git branch -d master # !
git checkout -b master   # create new master from upstream/master

现在我的master分支已经与upstream/master同步(你也可以重复上述步骤来同步其他分支)。


1
在本地的 master 分支上执行 git reset --hard upstream/master 命令即可完成任务。这样做可以避免丢失本地分支配置,例如默认的上游分支。 - tomekwi

0

没有足够的声望向x-yuri的回答添加评论,但它工作得很好并保留了历史记录。 我正在使用两个工作本地repo,并收到此错误:

中止:拒绝破坏性地覆盖repo历史记录, 因为这看起来不像是新的克隆。 (预期新的紧缩repo) 请在新的克隆上操作。如果您想继续,请使用--force。

与其担心 --force 标志的含义,我先在本地克隆了repo:

cd tempDir
git clone <location of repo to be merged> --no-local

并使用这个新克隆的副本执行x-yuri列出的一系列命令。 最后,在git filter-repo --to-subdirectory-filter a中,a是您为将要导入的存储库指定的根文件夹的名称。


0

我可以提供另一种解决方案(git子模块的替代方案)来解决你的问题 - gil (git links) 工具

它允许描述和管理复杂的 git 仓库依赖关系。

此外,它还提供了解决git递归子模块依赖问题的解决方案。

考虑下面这个项目的依赖关系图: 样例 git 仓库依赖关系图

然后你就可以定义一个.gitlinks文件来描述仓库之间的关系:

# Projects
CppBenchmark CppBenchmark https://github.com/chronoxor/CppBenchmark.git master
CppCommon CppCommon https://github.com/chronoxor/CppCommon.git master
CppLogging CppLogging https://github.com/chronoxor/CppLogging.git master

# Modules
Catch2 modules/Catch2 https://github.com/catchorg/Catch2.git master
cpp-optparse modules/cpp-optparse https://github.com/weisslj/cpp-optparse.git master
fmt modules/fmt https://github.com/fmtlib/fmt.git master
HdrHistogram modules/HdrHistogram https://github.com/HdrHistogram/HdrHistogram_c.git master
zlib modules/zlib https://github.com/madler/zlib.git master

# Scripts
build scripts/build https://github.com/chronoxor/CppBuildScripts.git master
cmake scripts/cmake https://github.com/chronoxor/CppCMakeScripts.git master

每一行都以以下格式描述git链接:
  1. 仓库的唯一名称
  2. 仓库相对路径(从.gitlinks文件所在路径开始)
  3. Git 仓库将在 git clone 命令中使用 要检出的仓库分支
  4. 空行或以#开头的行不会被解析(视为注释)。

最后,您需要更新您的根示例库:

# Clone and link all git links dependencies from .gitlinks file
gil clone
gil link

# The same result with a single command
gil update

作为结果,您将克隆所有必需的项目,并以适当的方式将它们链接在一起。

如果您想将某个仓库中的所有更改与子链接仓库中的所有更改一起提交,可以使用一个命令完成:

gil commit -a -m "Some big update"

拉取和推送命令的工作方式类似:

gil pull
gil push

Gil(git链接)工具支持以下命令:

usage: gil command arguments
Supported commands:
    help - show this help
    context - command will show the current git link context of the current directory
    clone - clone all repositories that are missed in the current context
    link - link all repositories that are missed in the current context
    update - clone and link in a single operation
    pull - pull all repositories in the current directory
    push - push all repositories in the current directory
    commit - commit all repositories in the current directory

了解更多关于Git 递归子模块依赖问题的信息。


-2

我不知道有什么简单的方法可以做到这一点。你可以尝试以下步骤:

  1. 使用git filter-branch 在XXX代码库中添加一个ZZZ的顶层目录。
  2. 将新分支推送到YYY代码库。
  3. 将推送的分支与YYY的主干合并。

如果需要更详细的信息,请告诉我。


-3

我认为你可以使用 'git mv' 和 'git pull' 来完成这个操作。

我是一个相对新手的 Git 用户 - 所以在处理主仓库时请小心 - 但我刚刚在一个临时目录中尝试了一下,似乎可以工作。

首先 - 将 XXX 的结构重命名为它在 YYY 中所需的结构:

cd XXX
mkdir tmp
git mv ZZZ tmp/ZZZ
git mv tmp ZZZ

现在XXX看起来是这样的:

XXX
 |- ZZZ
     |- ZZZ

现在使用“git pull”命令跨越获取更改:
cd ../YYY
git pull ../XXX

现在YYY看起来是这样的:

YYY
 |- ZZZ
     |- ZZZ
 |- (other folders that already were in YYY)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接