【问题标题】:How do I clone into a non-empty directory?如何克隆到非空目录?
【发布时间】:2018-02-17 20:52:15
【问题描述】:

我有目录 A 与目录 B 匹配的文件。目录 A 可能有其他需要的文件。目录 B 是一个 git repo。

我想将目录 B 克隆到目录 A 但 git-clone 不允许我这样做,因为该目录非空。

我希望它只是克隆 .git,因为所有文件都匹配,我可以从那里去?

我无法克隆到空目录,因为我在目录 A 中有文件不在目录 B 中,我想保留它们。

复制 .git 不是一个选项,因为我希望 refs 可以推/拉,而且我不想手动设置它们。

有什么办法吗?

更新:我认为这可行,任何人都可以看到任何问题吗? -->

cd a
git clone --no-hardlinks --no-checkout ../b a.tmp 
mv a.tmp/.git .
rm -rf a.tmp
git unstage # apparently git thinks all the files are deleted if you don't do this

【问题讨论】:

  • 只是想知道如果省略“--no-checkout”会发生什么,除了临时克隆会消耗更多的磁盘空间和时间。 'git unstage' 或其他东西仍然是必要的吗?
  • 可能是git-force-clone?

标签: git


【解决方案1】:

这对我有用:

git init
git remote add origin PATH/TO/REPO
git fetch
git reset origin/master  # Required when the versioned files existed in path before "git init" of this repo.
git checkout -t origin/master

注意:-t 将为您设置上游分支,如果这是您想要的,而且通常是这样。

【讨论】:

  • 当传入文件已经存在时(如原始问题所述),这在非空目录中不起作用。但是如果你在git fetch 之后git reset origin/master,它将起作用(同时保留任何本地更改)。
  • 致命:无法同时更新路径并切换到分支“master”。
  • 这个答案对我不起作用。当我git checkout ... git 抱怨我的所有文件都会被覆盖时,我应该先移动它们。当我首先执行 `git reset origin/master/` 时,checkout 命令会抱怨一个名为 master 的分支已经存在。
  • git checkout master 对我来说已经足够了。
  • 所有步骤都运行良好,但最后一个让我明白了:fatal: A branch named 'master' already exists。我想我真的不需要它。
【解决方案2】:

在以下 shell 命令中,existing-dir 是一个目录,其内容与 repo-to-clone git 存储库中的跟踪文件匹配。

# Clone just the repository's .git folder (excluding files as they are already in
# `existing-dir`) into an empty temporary directory
git clone --no-checkout repo-to-clone existing-dir/existing-dir.tmp # might want --no-hardlinks for cloning local repo

# Move the .git folder to the directory with the files.
# This makes `existing-dir` a git repo.
mv existing-dir/existing-dir.tmp/.git existing-dir/

# Delete the temporary directory
rmdir existing-dir/existing-dir.tmp
cd existing-dir

# git thinks all files are deleted, this reverts the state of the repo to HEAD.
# WARNING: any local changes to the files will be lost.
git reset --hard HEAD

【讨论】:

  • 我需要做git reset --hard HEAD 否则它不会放弃“已删除”的文件。
  • git reset HEAD 对我来说效果很好。 git reset --hard HEAD 会破坏文件中的任何更改,因此如果它们与存储库中的文件不完全相同,则不应这样做。
  • git reset HEAD 似乎对我没有任何影响。 git reset --hard HEAD 会 - 但这会丢失您对文件所做的任何更改。有更好的解决方案吗?
  • @Casey 的回答 -- git init/remote add/fetch/checkout -- 更简洁,不需要任何临时文件夹。
  • @Casey 的回答对我不起作用,因为文件夹中已经有需要保留但不在 git 存储库中的文件。这对于在运行创建文件和目录的安装脚本后更新配置很有用,但您需要在已安装项目的顶部更新/添加文件。
【解决方案3】:

对一个对我有用的答案稍作修改:

git init
git remote add origin PATH/TO/REPO
git pull origin master

立即开始在 master 分支上工作。

【讨论】:

  • 必须重置 HEAD --hard 来清理脏的现有目录,而不删除 gitignore 中指定的不相关文件
  • 这是真正为我工作的那个,而不是@cmcginty 的答案。
  • 这并不完全等同于 git-clone — 缺少的是 master 分支的上游信息。这可以通过添加git branch --set-upstream-to=origin/master master来解决。
  • 这个版本对我有用,只需要做一个 git reset --hard HEAD
【解决方案4】:

警告 - 这可能会覆盖文件。

git init     
git remote add origin PATH/TO/REPO     
git fetch     
git checkout -t origin/master -f

修改自 @cmcginty's answer - 没有 -f 它对我不起作用

【讨论】:

  • 你肯定需要在这之后用git checkout .签出所有文件吗?
【解决方案5】:

当我遇到同样的问题时,我最终会这样做(至少我认为这是同样的问题)。我进入目录 A 并运行 git init

由于我不希望目录 A 中的文件后跟 git,因此我编辑了 .gitignore 并将现有文件添加到其中。在此之后,我运行git remote add origin '<url>' && git pull origin master et voíla,B 被“克隆”到 A 中,没有任何问题。

【讨论】:

  • 当传入文件已经存在时(如原始问题所述),此技术在非空目录中不起作用。
【解决方案6】:

我刚才用过这个,需要最小潜在破坏性的命令:

cd existing-dir
git clone --bare repo-to-clone .git
git config --unset core.bare
git remote rm origin
git remote add origin repo-to-clone
git reset

瞧!

【讨论】:

  • 这些命令中的哪一个仍然具有潜在的破坏性?我猜是“git reset”,但没有任何选项是否还有破坏性潜力?
  • 没有命令是破坏性的。 git reset 只会重置索引,不会修改任何文件。
【解决方案7】:

另一个简单的食谱似乎对我很有效:

git clone --bare $URL .git
git config core.bare false

我签出包含现有文件的目录的主要用例是使用 Git 控制我的 Unix 点文件。在新帐户上,主目录中已经有一些文件,甚至可能是我想从 Git 获取的文件。

【讨论】:

  • 裸存储库的设置略有不同,虽然这确实有效,但我不推荐它。 :)
  • 你能说得更具体点吗?有什么不同?
  • 只有两个不同之处: 1.) .git/config 文件表明存储库是裸露的。 2.) 通常存储在.git 中的文件存储在根目录(您称之为.git
  • 这些正是克隆到.git并将core.bare设置为false会处理的更改,所以我仍然对这种方法感觉良好。
【解决方案8】:

这对我有用:

cd existing_folder
git init
git remote add origin path_to_your_repo.git
git add .
git commit
git push -u origin master

【讨论】:

    【解决方案9】:

    我计划用作登台 Web 服务器的新 Apache Web 目录(使用 WHM 创建的帐户)也遇到了类似的问题。我最初需要用那里的代码库克隆我的新项目,并通过从存储库中提取来定期部署更改。

    问题在于该帐户已包含以下 Web 服务器文件:

    .bash_history
    .bash_logout
    .bash_profile
    .bashrc
    .contactemail
    .cpanel/
    ...
    

    ...我不想删除或提交到我的存储库。我需要他们保持原样不动,不被追踪。

    我做了什么:

    我去了我的网络文件夹(existing_folder):

    cd /home/existing_folder
    

    然后:

    git init
    git remote add origin PATH/TO/REPO
    git pull origin master
    git status
    

    它(如预期的那样)显示了许多未暂存文件的列表 - 那些最初从我的 cPanel 网络帐户中已经存在的文件。

    然后,感谢this article,我刚刚将这些文件的列表添加到:

    **.git/info/exclude**
    

    此文件与.gitignore 文件几乎一样,允许您忽略暂存的文件。在此之后,我在 .git/ 目录中没有任何内容可提交 - 它就像个人的 .gitignore 一样,其他人无法看到。

    现在检查git status 返回:

    On branch master
    nothing to commit, working tree clean
    

    现在我可以通过从我的 git 存储库中拉取更改来将更改部署到此 Web 服务器。希望这可以帮助一些 Web 开发人员轻松创建登台服务器。

    【讨论】:

      【解决方案10】:

      也许我误解了您的问题,但是如果您将文件从 A 复制/移动到 git repo B 并使用 git add 添加所需的文件,会不会更简单?

      更新:来自 git 文档:

      仅当目录为空时才允许克隆到现有目录。

      来源:http://git-scm.com/docs/git-clone

      【讨论】:

      • 不,所有者和文件可以是任意的。这是针对多个开发人员的情况。我们都有现有的目录,目前只有一个有 git checkout。我们基本上都拥有相同的文件子集,因此我们希望其他开发人员能够在保留他们的文件的同时进行克隆。它应该尽可能优雅和方便。
      • 老实说,我看不出在这种情况下发展的意义。不能使用分支和合并操作吗?或者拥有具有外部依赖关系的子存储库?为什么要依赖单个“git checkout”?
      • 一个“单一的 git checkout”并不是整个考验的重点。只是这就是现状,我们需要一条前进的道路。我用似乎有效的解决方案更新了原始问题。不过,我感谢您的反馈。
      • 有很多合法的案例——我有一个复杂的文件夹树,必须在我的项目源设置之前设置,并且该文件夹树包含无法存储的许可作品例如在 GitHub 上。
      【解决方案11】:

      这是我正在做的事情:

      git clone repo /tmp/folder
      cp -rf /tmp/folder/.git /dest/folder/
      cd /dest/folder
      git checkout -f master
      

      【讨论】:

        【解决方案12】:

        以下内容对我有用。首先我要确保a 目录中的文件是源代码控制的:

        $ cd a
        $ git init
        $ git add .
        $ git commit -m "..."
        

        然后

        $ git remote add origin https://URL/TO/REPO
        $ git pull origin master --allow-unrelated-histories
        $ git push origin master
        

        【讨论】:

        • 这绝对救了我的命。荣誉和比特币!!
        【解决方案13】:

        这对我有用,但你应该将远程存储库文件合并到本地文件:

        git init
        git remote add origin url-to-git
        git branch --set-upstream-to=origin/master master
        git fetch
        git status
        

        【讨论】:

          【解决方案14】:

          我一直在寻找类似的东西,这就是我想出的:

          我的情况是我有一个活动的网络树,我试图为它创建一个远程存储库,而不移动当前网络树中的任何文件。这是我所做的:

          1. 转到网络树并运行git init
          2. 转到存储库的预期位置并运行:git clone --bare /path/to/web/repo
          3. 在我的远程仓库中编辑配置文件并删除 [remote "origin"] 部分。
          4. 在 Web 树中的 .git/config 中添加一个 [remote "origin"] 部分,指向新的远程存储库。

          【讨论】:

          • 我非常喜欢这个食谱。
          • 这里的git clone --bare是多余的和迂回的。首先为什么不只是git remote add origin <URL>
          【解决方案15】:

          我喜欢Dale's answer,我也加了

          git clone --depth 2 --no-checkout repo-to-clone existing-dir/existing-dir.tmp
          git branch dev_new214
          git checkout dev_new214
          git add .
          git commit
          git checkout dev
          git merge dev_new214
          

          较浅的深度避免了很多额外的早期开发提交。新分支为我们提供了一个很好的视觉历史,其中放置了来自该服务器的一些新代码。在我看来,这是完美的使用分支。感谢所有在这里发帖的人的深刻见解。

          【讨论】:

            【解决方案16】:

            我在尝试克隆到 c/code 时遇到了同样的问题

            但是这个文件夹包含一大堆项目。

            我在 c/code/newproject 中创建了一个新文件夹 并将我的克隆映射到此文件夹。

            桌面版 git 然后询问我的用户,然后克隆得很好。

            【讨论】:

              【解决方案17】:

              这个问题有很多答案,我认为其中没有一个涵盖将 A 初始化为 Git 存储库然后从 B 拉到 A 的选项。

              # Turn `A` into a Git repo and check in files
              git -C A init
              git -C A add --all
              git -C A commit -m "Add existing files"
              
              # Set `B` as a remote
              git -C A remote add local-B file:///B
              
              # Fetch & merge B 'master' to A 'master'
              git -C A pull --allow-unrelated local-B master
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-03-15
                • 2012-04-09
                • 1970-01-01
                • 1970-01-01
                • 2012-11-08
                • 2015-08-13
                相关资源
                最近更新 更多