我有一个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不是很好,所以有人可以告诉我我需要执行上述操作。
刚刚这样做,实际上非常简单。正确的方法是 -
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
你提到的解决方案应该可以工作,因为git首先根据文件的哈希值跟踪它们的位置。
如果作为移动文件的一部分,您将更改文件的内容。
在底部的情况下,尝试它,如果它不起作用,您可以在将更改推送到主repo之前恢复更改:)。这是我非常喜欢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/
然后在文件夹/ test中创建了一个文件
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 <[email protected]>
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 <[email protected]>
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
我希望这有帮助!
在Windows中,您可以执行以下操作:
当您在子文件夹中时
for /f %f in ('dir /b') do git mv %f ../
结果子文件夹中的所有对象都将位于父文件夹中
请注意:当子文件夹中的对象名称等于子文件夹时,可能会引发一些错误
是的,你可以简单地移动文件。但是你需要告诉git webapp文件夹中的旧文件已经消失了,也就是说,git需要更新已完成/已提交文件的索引。
所以你可以使用git add -A .
让git注意到所有的变化,或者使用git mv <files>
告诉git自己动作。 See the git mv man page。
--update。
你注意到你认为“.. git并没有真正处理移动或重命名......” - 我最初也很困惑,并且还没有完全理解索引的工作方式。一方面民间说git只拍摄快照并且不跟踪重命名,但是如果你更新.gitignore
,或者mv
文件等,那么你就会被它'失败'击中。这种'失败'是关于指数如何的混乱作品。
我的可视化是索引/暂存区域是一个地方,就像故事板墙一样,您可以在其中放置最新和最好的“已完成”文件的副本,包括其路径(使用git add
),并且它是提交的副本。如果你没有从故事板墙(即git rm
)中删除该副本,那么git将继续提交它,并且混乱很多(参见许多SO问题......)。在merge
s期间,git也以类似的方式使用索引
我只需从目标文件夹中执行此操作即可使其工作:
git mv webapp/* .
看起来这在Windows shell中不起作用(失败并出现错误Bad source
),但是如果你使用扩展*
通配符的Git Bash shell,它将在Windows中运行。
如果您使用PowerShell,则可以从项目根目录运行此命令,并将webapp的内容放在那里。
Get-ChildItem .\webapp\ | ForEach-Object { git mv $_.FullName .\ }
是的,git将跟踪过去内容的变化。它使用文件内容的哈希值,因此无论它们在目录结构中的位置如何,它们都将是同一个文件。
因此,您应该在一次提交中执行移动,然后在后续提交中修复任何编辑。这将使Git能够以最高效率确定重定向,并且不会对存储库中存储的数据量产生任何影响(因为您无论如何都要进行这些更改)。