Git:将“git clone”到现有文件夹的最佳实践是啥?

Posted

技术标签:

【中文标题】Git:将“git clone”到现有文件夹的最佳实践是啥?【英文标题】:Git: What's the best practice to "git clone" into an existing folder?Git:将“git clone”到现有文件夹的最佳实践是什么? 【发布时间】:2011-07-19 16:13:24 【问题描述】:

我有一个项目的工作副本,没有任何源代码控制元数据。现在,我想在这个文件夹中执行相当于 git-clone 的操作,并保留我的本地更改。

git-clone 不允许我克隆到现有文件夹中。这里的最佳做法是什么?

【问题讨论】:

更好的讨论是here。 @MEM 我更喜欢这个答案,但任何一个都可以...***.com/a/5377989/11236 @ripper234 - 是的。我处于同样的情况,我只是做了这些步骤,没有问题。一切都干净漂亮。我想这是一个偏好问题,最重要的是,正如你所说,两者都有效。干杯。 这太疯狂了,没有一种干净的方法可以实现它,当您想将项目克隆到已安装的共享文件夹时非常有用。 How do I clone into a non-empty directory?的可能重复 【参考方案1】:

我将git clone 复制到一个新目录并将现有目录的内容复制到新克隆。

【讨论】:

如果您这样做,请确保在提交之前仔细检查差异 - 这是一个绝对经典的案例,您可能会意外恢复在源代码库中所做的更改,因为每当您获得工作副本时- 因为工作副本中没有足够的信息来确定您所做的更改与您开始进行更改之前的更改,以便与 repo 中所做的其他更改合并。在这种情况下,我一次又一次地看到这种情况发生,以至于我“强烈劝阻”自己和与我一起工作的人不要这样做。 git clone wherever tmp && git mv tmp/.git . && rm -rf tmp 换句话说,将.git 目录移出临时克隆似乎比清除克隆的工作树并将现有文件复制到那里更简单。 @ChrisJohnsen:你应该把它变成一个答案,这绝对是最好的方法,恕我直言 @ChrisJohnsen git mv tmp/.git . 为我返回 fatal: cannot move directory over file, source=tmp/.git, destination=.git。有谁知道是什么问题? @Dennis,这是一个错字:该命令应该是简单的mv,而不是git mv;虽然这并不能解释为什么你已经有一个.git 文件(包含gitdir: some/path/to/a/git-dir,一个“gitfile”;如果它不在那里,那么你会看到fatal: Not a git repository (or any of the parent directories): .git)。【参考方案2】:

这可以通过克隆到一个新目录来完成,然后将.git 目录移动到您现有的目录中。

如果您现有的目录名为“code”。

git clone https://myrepo.com/git.git temp
mv temp/.git code/.git
rm -rf temp

这也可以在克隆命令期间不进行检出的情况下完成;更多信息可以在here找到。

【讨论】:

请注意,这正是他留在 cmets 中的 @ChrisJohnsen 的建议。我发现它很有用,并想把它变成一个实际的答案。克里斯,如果你最终提出答案,我会很乐意删除这个。 谢谢!虽然这缺少像“git checkout --”这样的步骤。因为它认为所有文件都被删除了,对吧? 不,只要您使用git clone 作为第一个命令,就不需要进一步的结帐命令。如果您在第一步中使用 git clone --no-checkout 之类的东西,那么在移动 .git 目录后,将需要使用 git reset HEAD 告诉 git 文件没有被删除。 我会将其添加为第三步:mv temp/.gitignore code/.gitignore @KalpeshSoni,是的,git 会知道修改后的文件,并且可以使用普通的 git 命令(例如git status)查看更改。【参考方案3】:
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed

【讨论】:

使用 git reset --hard 将取消本地文件更改,特别是不是此 OP 要求的内容。应该改用--mixed --mixed 可以省略,因为它是默认值。【参考方案4】:

对此有两种方法。在可能的情况下,我会为您的新 git 工作目录创建一个干净的文件夹,然后再复制您的版本。这可能看起来像*:

mv $dir $dir.orig
git clone $url $dir
rsync -av --delete --exclude '.git' $dir.orig/ $dir/
rm -rf $dir.orig

此时,您应该有一个非常干净的工作副本,并将您以前的工作文件夹作为当前工作目录,因此如果您运行 git status,任何更改(包括文件删除)都会显示在雷达上。

另一方面,如果你真的必须反其道而行之,你可以通过以下方式获得相同的结果:

cd $dir
git clone --no-checkout $url tempdir
mv tempdir/.git .
rmdir tempdir
git reset --mixed HEAD

无论哪种方式,我要做的第一件事就是运行 git stash 之类的东西来获取所有本地更改的副本,然后您可以重新应用它们并处理您想要提交的更改。

* 这两个示例都假设您从项目父目录中的 shell 开始。

【讨论】:

【参考方案5】:

不要克隆,取而代之。在回购中:

git init
git remote add origin $url_of_clone_source
git fetch origin
git checkout -b master --track origin/master # origin/master is clone's default

然后你可以重置树以获得你想要的提交:

git reset origin/master # or whatever commit you think is proper...

你就像被克隆了一样。

这里有一个有趣的问题(也是一个没有答案的问题):如何找出你的裸树基于哪个提交,从而重置到哪个位置。

【讨论】:

我不喜欢这个 - 根据 github 设置“提示:凭据帮助程序仅在您克隆 HTTPS 存储库 URL 时有效。”我正在使用凭证助手,这让我陷入了一个漫长而毫无结果的兔子洞。 'git checkout --track origin/master' 也可以很好地代替 'git checkout -b master --track origin/master'。不需要重置。 我收到错误“Git 错误:以下未跟踪的工作树文件将被结帐覆盖”,所以我添加了这个命令:git clean -d -fx "" 绝对不建议在所有情况下使用,但这正是我所需要的。 @AndreasKrey 您的原始答案(我进入编辑历史以查看)正是问题(和我)所需要的。结帐时更改的答案不使用 -f,它会丢弃本地更改,这正是我想要的。如果我是你,我会考虑回滚到你原来的答案。【参考方案6】:

使用临时目录很好,但如果您想避免该步骤,这将起作用。从工作目录的根目录:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master

【讨论】:

git reset --hard origin/master 将删除所有本地文件。 补充上面已经指出的内容,hardmixed 之间的区别在于混合将保留本地更改(因此,如果您稍后尝试拉取它会显示例如 无法使用 rebase 拉取:您有未暂存的更改。请提交或存储它们),而 hard 将丢弃这些本地更改 你拼错了远程。【参考方案7】:

如果您至少使用 git 1.7.7(它教导了 clone --config 选项),则将当前目录转换为工作副本:

git clone example.com/my.git ./.git --mirror --config core.bare=false

这是由:

将存储库克隆到新的.git 文件夹中 --mirror 使新克隆成为纯元数据文件夹,因为 .git 需要 --config core.bare=false--mirror 选项的隐式 bare=true 相对应,从而允许存储库具有关联的工作目录并像普通克隆一样工作

如果.git 元数据目录已存在于您希望转换为工作副本的目录中,这显然不起作用。

【讨论】:

请注意,此技术将导致本地配置的[core] 部分包括bare = true bare = false。更大的问题是它会为origin 远程设置错误的值,其中[remote "origin"] 部分包括mirror = true 和一个无法与工作副本一起正常工作的获取规范。解决这些问题后,正常克隆并移动新工作副本的.git 会更有效。【参考方案8】:

我做了以下检查现有目录中的主分支:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft

【讨论】:

这是一个很好的答案,可以避免任何文件系统问题。 这应该是公认的答案,因为它不是黑客。 实际上,这正是 OP(和我)想要的,即覆盖本地更改。 有人能解释一下为什么这里使用-t 标志吗? From git checkout --help, -t or --track 用于使指定的分支成为默认的上游分支。据我所知,它相当于git push -u *branch*,所以从那时起你就可以做git push。我个人不知道它对git checkout 有何影响,但我猜也是这样。【参考方案9】:

要将 git repo 克隆到一个空的现有目录中,请执行以下操作:

cd myfolder
git clone https://myrepo.com/git.git . 

注意. 在您的git clone 命令末尾。这会将 repo 下载到当前工作目录中。

【讨论】:

fatal: destination path '.' already exists and is not an empty directory. 目录必须为空。 OP 询问如何克隆到现有项目中,并指出 git clone 抱怨。错误的答案。 这仅在您创建新目录时有效,运行上述命令而不使用“git init” 目录必须为空才能使其工作,其中包括隐藏文件,例如.DS_Store。使用命令行创建目录,你不会有问题。【参考方案10】:

已经有很多答案可以按照 OP 的要求进行。但值得注意的是,相反的方式要简单得多:

git clone repo-url tmp/
cp -R working/ tmp/

您现在拥有所需的目标状态 - 新克隆 + 本地更改。

【讨论】:

【参考方案11】:

通常我会先克隆初始存储库,然后将现有文件夹中的所有内容移动到初始存储库。它每次都有效。

这种方法的优点是您不会丢失初始存储库的任何内容,包括 README 或 .gitignore。

您也可以使用下面的命令来完成这些步骤:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo

【讨论】:

【参考方案12】:

这是我遇到的所有方法中最好的

仅将存储库的 .git 文件夹(不包括文件,因为它们已经在 existing-dir 中)克隆到一个空的临时目录中

    git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp //可能需要 --no-hardlinks 来克隆本地仓库

将 .git 文件夹移动到文件所在的目录。 这使得 existing-dir 成为一个 git repo。

    mv existing-dir/existing-dir.tmp/.git existing-dir/

删除临时目录

    rmdir existing-dir/existing-dir.tmp

    cd existing-dir

Git 认为所有文件都已删除,这会将 repo 的状态恢复为 HEAD。

警告:对文件的任何本地更改都将丢失。

    git reset --mixed HEAD

【讨论】:

硬重置似乎在 99% 的情况下您需要这样做。【参考方案13】:

您可以通过递归输入以下命令行来实现:

mkdir temp_dir   //  Create new temporary dicetory named temp_dir
git clone https://www...........git temp_dir // Clone your git repo inside it
mv temp_dir/* existing_dir // Move the recently cloned repo content from the temp_dir to your existing_dir
rm -rf temp_dir // Remove the created temporary directory

【讨论】:

【参考方案14】:

只需使用 .在git clone 命令的末尾(位于该目录中),如下所示:

cd your_dir_to_clone_in/
git clone git@github.com/somerepo/ .

【讨论】:

不起作用:致命:目标路径'。'已存在且不是空目录。 不能克隆到非空目录中。【参考方案15】:

如果你正在克隆同一个仓库,则通过现有仓库运行以下 sn-p

git pull origin master

【讨论】:

【参考方案16】:
git init
git remote add origin git@github.com:<user>/<repo>.git
git remote -v
git pull origin master

【讨论】:

如果当前工作副本的文件不存在于拉取的分支中,这将失败:“以下未跟踪的工作树文件将被合并覆盖”(可能来自一个不同的分支)。 是的。仅当您在开始在目录中工作之前拉取您的存储库时。 @GinoMempin【参考方案17】:

供参考,来自 Gitlab 命令行指令:

推送现有文件夹

cd existing_folder
git init
git remote add origin <url>
git add .
git commit -m "Initial commit"
git push -u origin master

或推送现有的 Git 存储库

cd existing_repo
git remote rename origin old-origin
git remote add origin <url>
git push -u origin --all
git push -u origin --tags

【讨论】:

以上是关于Git:将“git clone”到现有文件夹的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章

git clone 怎么复制到指定文件夹

git clone 命令

git clone 远程库到本地的步骤

git clone报错处理

GIT clone分支 去掉根目录

一招 git clone 加速 实测有效