如何在文件夹层次结构中将所有git内容向上移动一级?

时间:2011-08-20 09:14:43

标签: git directory

我有一个git存储库,其结构如下:

+--repo.git
|
+----+bootstrap.py
+----+buildout.cfg
+----+.gitignore
+----+webapp
|
+---------+manage.py
+---------+modules
+---------+templates
+---------+static
+---------+...
+---------+...

我想将webapp文件夹的内容提升一级。我的结果回购应该如下:

+--repo.git
|
+----+bootstrap.py
+----+buildout.cfg
+----+.gitignore
+----+manage.py
+----+modules
+----+templates
+----+static
+----+...
+----+...

我可以通过简单地将webapp目录的所有文件向上移动一级,删除空webapp目录然后提交更改来完成此操作吗?这会保留webapp目录下的文件的提交历史记录吗?

虽然对很多人来说这是一个非常简单的问题,但我想确定一下。我最不想要的就是喝汤。


我尝试移动文件但是我丢失了提交历史记录,因为git并没有真正处理移动或重命名。我知道即使它在日志中显示为新文件,仍然可以使用git log中的一些选项查看文件的提交历史记录。

从我读过的内容来看,实现这一目标的最佳方法是使用git-filter。我对shell或git不是很好,所以有人可以告诉我我需要执行上述操作。

9 个答案:

答案 0 :(得分:50)

刚刚这样做,实际上非常简单。正确的方法是 -

git mv repo.git/webapp/* repo.git/.

然后

git rm repo.git/webapp

后跟

git add * 
git commit -m "Folders moved out of webapp directory :-)"

答案 1 :(得分:21)

Sumeet答案的另一个变体 - 在上面的存储库目录中" webapp"执行以下命令:

git mv webapp/* ./ -k

-k - 包含尚未受版本控制的文件,否则您将获得:

fatal: not under version control, source=webapp/somefile, destination=somefile

答案 2 :(得分:4)

你提到的解决方案应该可行,因为git首先根据文件的哈希值跟踪更改,然后根据文件的位置进行更改。

如果作为移动文件的一部分,您将更改文件的内容。

底部,尝试它,如果它不起作用,您可以在将更改推送到主仓库之前还原更改:)。这是我非常喜欢git的原因之一。

修改

我忘了提到要在重命名后查看更改,您需要使用'--follow'参数。检查此示例

首先,我创建了一个新的git repo

94:workspace augusto$ mkdir gittest
94:workspace augusto$ cd gittest/
94:gittest augusto$ git init
Initialized empty Git repository in /Volumes/Data/dev/workspace/gittest/.git/

然后在文件夹/测试

中创建了一个文件
94:gittest augusto$ mkdir folder
94:gittest augusto$ vi folder/test
94:gittest augusto$ git add folder/test
94:gittest augusto$ git commit -am "added file"
[master (root-commit) 7128f82] added file
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 folder/test

然后将文件移至 newfolder / test

94:gittest augusto$ mkdir newfolder
94:gittest augusto$ mv folder/test newfolder/
94:gittest augusto$ git add newfolder/test 
94:gittest augusto$ git commit -am "moved/renamed file"
[master 4da41f5] moved/renamed file
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename {folder => newfolder}/test (100%)

git log --follow newfolder/test显示完整的历史记录(我添加了参数-p以显示更多信息,例如路径)。

94:gittest augusto$ git log --follow -p newfolder/test 
commit 4da41f5868ab12146e11820d9813e5a2ac29a591
Author: Augusto Rodriguez <xxxx@gmail.com>
Date:   Sat Aug 20 18:20:37 2011 +0100

    moved/renamed file

diff --git a/folder/test b/newfolder/test
similarity index 100%
rename from folder/test
rename to newfolder/test

commit 7128f8232be45fd76616f88d7e164a840e1917d5
Author: Augusto Rodriguez <xxxx@gmail.com>
Date:   Sat Aug 20 18:19:58 2011 +0100

    added file

diff --git a/folder/test b/folder/test
new file mode 100644
index 0000000..3b2aed8
--- /dev/null
+++ b/folder/test
@@ -0,0 +1 @@
+this is a new file

我希望这有帮助!

答案 3 :(得分:2)

在Windows中

可以执行以下操作:

当您在子文件夹

for /f %f in ('dir /b') do git mv %f ../

结果子文件夹中的所有对象都将位于父文件夹

请注意:如果子文件夹中的对象名称等于子文件夹,则可能会出现一些错误

答案 4 :(得分:1)

是的,你可以简单地移动文件。但是你需要告诉git webapp文件夹中的旧文件已经消失了,也就是说,git需要更新已完成/已提交文件的索引。

因此,您可以使用git add -A .让git注意到所有更改,或使用git mv <files>告诉git自行执行此操作。 See the git mv man page

- 更新

你注意到你认为“.. git并没有真正处理移动或重命名......” - 我起初也很困惑,并且还没有完全理解索引的工作方式。一方面民间说git只拍摄快照而不跟踪重命名,但如果你更新.gitignoremv一个文件等,你就会被它“失败”。这个'失败' '是关于指数如何的混淆。

我的可视化是索引/暂存区域是一个地方,就像故事板墙一样,您可以在其中放置最新和最好的“已完成”文件的副本,包括其路径(使用git add),以及它是提交的副本。如果你没有从故事板墙上取下那份副本(即git rm),那么git将继续提交它,并且混乱很多(参见许多SO问题......)。 git在merge期间也以类似的方式使用索引

答案 5 :(得分:1)

我只需从目标文件夹中执行此操作即可使其正常工作:

git mv webapp/* .

似乎这在Windows shell中无效(失败并显示错误Bad source),但如果使用Git Bash shell,在Windows中运行展开*通配符。

答案 6 :(得分:1)

如果您使用的是PowerShell,则可以从项目根目录运行此命令,它将把webapp的内容放在此处。

Get-ChildItem .\webapp\ | ForEach-Object { git mv $_.FullName .\ }

答案 7 :(得分:0)

是的,git会跟踪过去内容的变化。它使用文件内容的哈希值,因此无论它们在目录结构中的位置如何,它们都将是同一个文件。

因此,您应该在一次提交中执行移动,然后在后续提交中修复任何编辑。这将使Git能够以最高效率确定重定向,并且不会对存储库中存储的数据量产生任何影响(因为您无论如何都要进行这些更改)。

答案 8 :(得分:0)

在Windows中,使用Bash可以完成以下工作:

git mv /c/REPO_FOLDER/X_FOLDER/Y_FOLDER/Z_FOLDER/* /c/REPO_FOLDER/X_FOLDER/Y_FOLDER