Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将现有Git存储库导入另一个?_Git_Merge_Git Merge - Fatal编程技术网

如何将现有Git存储库导入另一个?

如何将现有Git存储库导入另一个?,git,merge,git-merge,Git,Merge,Git Merge,我在一个名为XXX的文件夹中有一个Git存储库,第二个Git存储库名为YYY 我想将XXX存储库作为名为ZZZ的子目录导入YYY存储库,并将所有XXX的更改历史添加到YYY 之前的文件夹结构: ├── XXX │ ├── .git │ └── (project files) └── YYY ├── .git └── (project files) 文件夹结构之后: YYY ├── .git <-- This now contains the change his

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

我想将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)
YYY

├── .git我认为您可以使用“git mv”和“git pull”来实现这一点

我是一个普通的GitNoob——所以要小心你的主存储库——但我只是在一个临时目录中尝试了一下,它似乎起了作用

首先-重命名XXX的结构,以匹配在YYY内时的外观:

cd XXX
mkdir tmp
git mv ZZZ tmp/ZZZ
git mv tmp ZZZ
现在XXX看起来像这样:

XXX
 |- ZZZ
     |- ZZZ
YYY
 |- ZZZ
     |- ZZZ
 |- (other folders that already were in YYY)
现在使用“git pull”获取跨以下对象的更改:

cd ../YYY
git pull ../XXX
现在YYY看起来像这样:

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

我不知道有什么简单的方法可以做到这一点。您可以这样做:

  • 使用git筛选器分支在XXX存储库中添加ZZZ超级目录
  • 将新分支推送到YYY存储库
  • 将推送的分支与YYY的主干合并

  • 如果这听起来很吸引人,我可以编辑细节。

    在Git存储库中有一个著名的例子,在Git社区中统称为“”(在发送给Git mailinglist的电子邮件中使用的主题行Linus Torvalds之后,该邮件列表描述了此合并)。在本例中,
    gitk
    gitgui现在是Git本身的一部分,实际上是一个单独的项目。Linus以一种

    • 它出现在Git存储库中,就好像它一直是作为Git的一部分开发的一样
    • 所有的历史都完好无损
    • 它仍然可以在其旧存储库中独立开发,只需对其进行
      git-pull
      ed更改即可
    这封电子邮件包含了复制所需的步骤,但它不是为胆小的人准备的:首先,Linus写了Git,所以他可能比你或我更了解Git,其次,这是近5年前的事了,Git从那时起有了很大的改进,所以现在可能更容易了


    特别是,我想现在人们会使用gitk子模块,在这种特定情况下。

    最简单的方法可能是将XXX内容拉入YYY中的一个分支,然后将其合并到master中:

    在YYY中:

    git remote add other /path/to/XXX
    git fetch other
    git checkout -b ZZZ other/master
    mkdir ZZZ
    git mv stuff ZZZ/stuff                      # repeat as necessary for each file/dir
    git commit -m "Moved stuff to ZZZ"
    git checkout master                
    git merge ZZZ --allow-unrelated-histories   # should add ZZZ/ to master
    git commit
    git remote rm other
    git branch -d ZZZ                           # to get rid of the extra branch before pushing
    git push                                    # if you have a remote, that is
    
    事实上,我只是用我的几份回购协议尝试了一下,效果不错。不同的是,它不会让你继续使用另一种回购协议,但我认为你无论如何都不会指定


    注意:由于这最初是在2009年编写的,git添加了下面答案中提到的子树合并。我今天可能会使用这种方法,当然这种方法仍然有效。

    简单的方法是使用git格式的补丁

    假设我们有两个git存储库foobar

    foo包含:

    • foo.txt
    • 吉特先生
    包含:

    • bar.txt
    • 吉特先生
    我们希望以foo结束,其中包含历史记录和以下文件:

    • foo.txt
    • 吉特先生
    • foobar/bar.txt
    为此:

     1. create a temporary directory eg PATH_YOU_WANT/patch-bar
     2. go in bar directory
     3. git format-patch --root HEAD --no-stat -o PATH_YOU_WANT/patch-bar --src-prefix=a/foobar/ --dst-prefix=b/foobar/
     4. go in foo directory
     5. git am PATH_YOU_WANT/patch-bar/*
    
    如果我们想重写bar中的所有消息提交,我们可以这样做,例如在Linux上:

    git filter-branch --msg-filter 'sed "1s/^/\[bar\] /"' COMMIT_SHA1_OF_THE_PARENT_OF_THE_FIRST_BAR_COMMIT..HEAD
    

    这将在每个提交消息的开头添加“[bar]”。

    如果您希望保留第二个存储库的确切提交历史记录,从而也能够在将来轻松合并上游更改,那么下面是您想要的方法。它会导致导入到repo中的子树的未修改历史加上一个合并提交,以将合并的存储库移动到子目录

    git remote add XXX_remote <path-or-url-to-XXX-repo>
    git fetch XXX_remote
    git merge -s ours --no-commit --allow-unrelated-histories XXX_remote/master
    git read-tree --prefix=ZZZ/ -u XXX_remote/master
    git commit -m "Imported XXX as a subtree."
    
    Git在进行合并之前会自行确定根的位置,因此不需要在后续合并中指定前缀

    缺点是,在合并的历史记录中,文件是不固定的(不在子目录中)。因此,
    git log ZZZ/a
    将显示除合并历史记录中的更改以外的所有更改(如果有)。你可以做:

    git log --follow -- a
    
    git log --follow -- a
    
    但这不会显示合并历史中的其他更改

    换句话说,如果不更改存储库中的
    ZZZ
    文件
    XXX
    ,则需要指定
    --follow
    和一个不固定的路径。如果在两个存储库中都更改了它们,则有两个命令,其中没有一个显示所有更改

    2.9之前的Git版本:您不需要将
    --允许不相关的历史记录
    选项传递到
    Git合并

    另一个答案中使用
    readtree
    并跳过
    merge-sours
    步骤的方法实际上与使用cp复制文件并提交结果没有什么不同


    原来的来源是从。而且。

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

    ALL_COMMITS=$(git log --reverse --pretty=format:%H -- ZZZ | tr '\n' ' ')
    
    这将为您提供一个以空格分隔的列表,其中列出了影响我要导入的文件(ZZZ)的所有提交(您可能还需要添加--follow以捕获重命名)。然后,我进入目标存储库(YYY),将另一个存储库(XXX)添加为远程存储库,从中提取数据,最后:

    git cherry-pick $ALL_COMMITS
    

    这会将所有提交添加到您的分支中,因此您将拥有所有文件及其历史记录,并且可以对它们执行任何您想要的操作,就好像它们一直在这个存储库中一样。

    添加另一个答案,因为我认为这更简单一些。将repo_dest拉入repo_to_import,然后推式设置上游url:repo_dest master

    这种方法对我来说很有效,它将几个较小的回购协议导入到一个较大的回购协议中

    如何导入:repo1\u到repo\u导入到repo\u dest# 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
    git remote add merge-source-repo <path-to-your-source-repository>
    git fetch merge-source-repo
    git merge -s ours --no-commit merge-source-repo/subtree-split-result
    git read-tree --prefix=<destination-path-to-merge-into> -u merge-source-repo/subtree-split-result
    
    git status
    git commit
    
    git subtree add -P <prefix> <repo> <rev>
    
    git subtree add -P ZZZ /path/to/XXX.git master
    
    git log --follow -- a
    
    $ git branch -d B-master
    
    function git-add-repo
    {
        repo="$1"
        dir="$(echo "$2" | sed 's/\/$//')"
        path="$(pwd)"
    
        tmp="$(mktemp -d)"
        remote="$(echo "$tmp" | sed 's/\///g'| sed 's/\./_/g')"
    
        git clone "$repo" "$tmp"
        cd "$tmp"
    
        git filter-branch --index-filter '
            git ls-files -s |
            sed "s,\t,&'"$dir"'/," |
            GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
            mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
        ' HEAD
    
        cd "$path"
        git remote add -f "$remote" "file://$tmp/.git"
        git pull "$remote/master"
        git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
        git remote remove "$remote"
        rm -rf "$tmp"
    }
    
    cd current/package
    git-add-repo https://github.com/example/example dir/to/save
    
    repo="https://github.com/example/example"
    path="$(pwd)"
    
    tmp="$(mktemp -d)"
    remote="$(echo "$tmp" | sed 's/\///g' | sed 's/\./_/g')"
    
    git clone "$repo" "$tmp"
    cd "$tmp"
    
    GIT_ADD_STORED=""
    
    function git-mv-store
    {
        from="$(echo "$1" | sed 's/\./\\./')"
        to="$(echo "$2" | sed 's/\./\\./')"
    
        GIT_ADD_STORED+='s,\t'"$from"',\t'"$to"',;'
    }
    
    # NOTICE! This paths used for example! Use yours instead!
    git-mv-store 'public/index.php' 'public/admin.php'
    git-mv-store 'public/data' 'public/x/_data'
    git-mv-store 'public/.htaccess' '.htaccess'
    git-mv-store 'core/config' 'config/config'
    git-mv-store 'core/defines.php' 'defines/defines.php'
    git-mv-store 'README.md' 'doc/README.md'
    git-mv-store '.gitignore' 'unneeded/.gitignore'
    
    git filter-branch --index-filter '
        git ls-files -s |
        sed "'"$GIT_ADD_STORED"'" |
        GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
        mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
    ' HEAD
    
    GIT_ADD_STORED=""
    
    cd "$path"
    git remote add -f "$remote" "file://$tmp/.git"
    git pull "$remote/master"
    git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
    git remote remove "$remote"
    rm -rf "$tmp"
    
    # 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
    
    # 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
    
    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
    
    cd a
    git filter-repo --to-subdirectory-filter a
    cd ..
    cd b
    git remote add a ../a
    git fetch a
    git merge --allow-unrelated-histories a/master
    git remote remove a
    
    cd tempDir
    git clone <location of repo to be merged> --no-local