将git仓库移动到上一级目录

99

Git 初学者问题:

我有一个小的私人 Web 项目,使用 msysgit 进行本地版本控制。由于只是给自己用,所以没有外部存储库,可以随意操作。

我已经在项目目录中设置了它,即在 "webroot" 中。

现在必须创建第二个目录,放置在 webroot 平行的位置。我们称其为 assets。

因此,目前的结构如下:

\ project directory
----\webroot
----\assets
我希望能在git仓库中包含这个新目录,以便我也可以版本化存储在其中的文件的更改,但当然我不能使用“git add ../assets”。我也不想在project_directory中创建一个新的git项目,因为这将丢失我之前的提交记录。
那么,我该如何将仓库从“webroot”移动到“project_directory”,同时保留我的提交记录并能够包含“assets”?

不完全是您所要求的,但您可以创建一个分支并将资产添加到其中。 - Mr. L
5个回答

88

所以,你希望你的git仓库看起来像这样:

<projectdir>
    /.git
    /webroot
    /assets

为此,您必须将现有文件在您的存储库中移动到一个新的webroot子目录中。

cd <git repo root>
mkdir webroot
git mv <all your files> webroot
git commit --all -m "moved all existing files to new 'webroot' directory"

然后,在您的本地文件系统中,您希望将克隆体移到当前目录的上一级目录:

cd <projectdir>
mv webroot/* .
rmdir webroot

然后你需要将 assets 目录(和文件)添加到 git 仓库:

git add assets
git commit -m "added assets to the repo"

3
好的,显然我没有提供足够的信息。仓库已经在 /projectdir/webroot/ 中,因为这是它最初创建的位置。由于资产目录已经存在,我希望仓库表现得像它是在 /projectdir/ 中创建的,但实际上并不是。git mv 不允许我将文件移动到仓库之外。 - Sorcy
@Sorcy:我相信我理解你想做什么。我更新了我的答案以澄清它。 - Tim Henigan
谢谢,这正是我在寻找的解决方案。 :) - Sorcy
2
我发现这个解决方案还需要 mv webroot/.* .,以便移动仓库和.gitignore文件。 - katriel
git mv * webroot 不起作用,因为 bash 通配符 * 也会被替换为 webroot,使命令变成 git mv webroot webroot。Git 将在此处失败。它遇到问题的另一个文件夹是 .git。所以我不得不使用特殊的 bash 环境变量 GLOBIGNORE=webroot:.git,这样 * 就不会被这两个目录替换。由于这个,我不必手动移动几十个 git mv - 我的目录有很多文件夹和文件。我只需要手动移动 .git 文件夹。 - Koshmaar
显示剩余2条评论

24

你也可以将.git目录移动到上一级并更新你的工作树。

cd projectdir
mv ./webroot/.git ./.git
git config core.worktree /absolute-path-to-project-dir
git add assets
git commit -m 'adding assets folder'

不确定,但我非常肯定 core.worktree 的路径必须是绝对路径。


1
这是对我有效的顺序。当我在想要移动.git文件的文件夹中时:mv .git / ../ - anevaude
1
我在类似的情况下也遇到过这个问题,我不得不重新将已经添加到先前位置的文件添加到仓库中。因此,我认为我丢失了那些文件的git历史记录。 - aneccodeal

15

我假设你的意思是重新编写历史记录,将所有文件都包含在所有版本中,就好像它们一直在一个名为webroot/的子目录中而不是在根目录中

git filter-branch手册提供了答案,这里是一个改进版,可以重写所有现有的引用(分支)和标签:

time git filter-branch --index-filter 'git ls-files -s |
         sed "s-\t\"*-&webroot/-" |
         GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && 
     mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' --tag-name-filter cat -- --all

已经采取措施使其成为仅索引操作,因此即使对于大型存储库,该过程也将快速运行。请记住,在满意后要清除原始引用(.git/refs/original/*)并重新打包存储库以消除过时的树对象。


2
你能解释一下如何摆脱原始引用并重新打包存储库吗?只是GC还是其他什么? - NateS
2
这正是我想要的。谢谢!对于那些感到困惑的人,此操作应在完成Tim Henigan建议的内容之后进行。 - Youwei Liang
起初我有些困惑,因为上面的代码会在现有的 webroot/ 文件夹内创建一个新的 webroot/ 文件夹(这样你就会得到 project directory/webroot/webroot/),并将 project directory/webroot/ 的内容移动到 project directory/webroot/webroot/ 中。关键是要将 project directory/ 的所有内容移动到 project directory/webroot/ 中,并根据需要进行重命名。 - Lino Ferreira

5

你的提交并没有与存储在git仓库中的“webroot”文件夹本地绑定。

你可以直接删除webroot目录,重新在新位置“/project directory”中检出仓库,添加资源目录并提交。

rm -Rf webroot
git clone path-to-repo
git add assets 
git commit -m "Added assets directory"
git push

0
以下命令将重写您的 Git 历史记录。它看起来就像内容一直在 webroot 中一样。通常如果多个人正在使用存储库,则重写历史记录会带来麻烦。由于您是独自工作,所以应该没问题。
git filter-branch --index-filter '
    git read-tree --prefix="webroot/" $GIT_COMMIT && \
    git ls-files \
      | sed "s/\/.*//" \
      | sort \
      | uniq \
      | grep -v "^webroot" \
      | xargs -L1 git rm -r --cached > /dev/null'

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