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

我有一个结构如下所示的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目录下的文件的提交历史?

尽pipe对于你们许多人来说,这是一个非常简单的问题,但我想确定一下。 我想要的最后一件事是混合汤。


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

从我读过的,完成这个最好的方法是使用git-filter 。 我用shell或git不太好,所以有人可以告诉我需要执行上述操作。

只是做了这个,实际上很简单。 正确的做法是 –

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

接着

 git rm repo.git/webapp 

其次是一个

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

Sumeet的答案的另一个变种 – 在“webapp”上方的资源库目录中执行以下命令:

 git mv webapp/* ./ -k 

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

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

你提到的解决scheme应该可以工作,因为git会根据文件的哈希值,然后根据它们的位置进行更改。

这不会工作,如果作为移动文件的一部分,你改变文件的内容。

底部的情况下,尝试它,如果它不起作用,你可以恢复更改之前,推动到主回购协议的变化:)。 这是我真正喜欢git的原因之一。

编辑

我忘了提及要在重命名后查看更改,您需要使用“–follow”参数。 检查这个例子

首先,我创build了一个新的git回购

 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/ 

然后在文件夹/testing中创build一个文件

 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 

然后将文件移到新的文件夹/testing

 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显示完整的历史logging(我已经添加了参数-p显示更多的信息,如path)。

 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 

我希望这有帮助!

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

所以你可以使用git add -A . 使git注意到所有的变化,或者使用git mv <files>来告诉git自己做这个动作。 请参阅git mv手册页 。

–update。

你注意到你认为“git并没有真正处理一个动作或者重命名……” – 起初我也感到困惑,并没有完全理解索引的工作方式。 一方面民间说git只拍摄快照而不跟踪重命名,但是如果你更新.gitignore或者mv文件等等,那么你会碰到“失败”。这个“失败”是一个混淆索引工作。

我的可视化是Index / Staging区域是一个地方,就像一个故事板墙,在那里你放置一个最新的和最伟大的“完成”文件的副本,包括它的path,(使用git add ),是这样的副本承诺。 如果你不从故事板墙上取下这个副本(即git rm ),那么git将继续提交它,并且混乱不已(见许多SO问题)。 在merge过程中,git也以类似的方式使用索引

在Windows中,您可以执行以下操作:

当你在孩子的文件夹

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

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

请注意:当名称等于子文件夹的子文件夹中有对象时,可能会引发一些错误

是的,git会跟踪过去内容的变化。 它使用文件内容的散列,不pipe它们在目录结构中的位置,它们将是相同的文件。

因此,您应该在一次提交中执行该操作,然后在后续提交中修改所有编辑。 这将使Git能够以最高效率确定redirect,并且不会对存储库中存储的数据量产生任何影响(因为您将会进行这些更改)。