我有一个/foo/bar大型提交历史和多个分支的git repo .
我现在想要/foo/baz处于相同的回购中/foo/bar,这(我认为)意味着我需要创建一个新的回购/foo.但是,我想保留我所做的变化的历史/foo/bar.
我首先想到的是git format-patch,然后是apply,但是不保留提交消息.
Wal*_*ndt 25
你想要的是git filter-branch,它可以将整个存储库移动到一个子树中,通过使它看起来像是一直都是那样来保存历史.在使用之前备份您的存储库!
这是魔术.在/foo/bar,运行:
git filter-branch --commit-filter '
TREE="$1";
shift;
SUBTREE=`echo -e 040000 tree $TREE"\tbar" | git mktree`
git commit-tree $SUBTREE "$@"' -- --all
Run Code Online (Sandbox Code Playgroud)
这将使/foo/bar存储库具有另一个"bar"子目录,其子目录包含其整个历史记录中的所有内容.然后,您可以将整个仓库移动到该foo级别并向其添加baz代码.
更新:
好的,这是正在发生的事情.提交是指向"树"的链接(将其视为表示整个文件系统子目录内容的SHA)以及一些"父"SHA和一些元数据链接作者/消息/等.该git commit-tree命令是将所有这些包装在一起的低级位.--commit-filter被视为shell函数并在git commit-tree过滤过程中代替运行的参数,必须像它一样运行.
我正在做的是获取第一个参数,提交原始树,并构建一个新的"树对象",通过git mktree另一个低级别的git命令将其显示在子文件夹中.要做到这一点,我必须管它看起来像一个git树,即一组(模式SP类型SP SHA TAB文件名)行; 因此,回声命令.mktree当我链接到真实时,输出被替换为第一个参数commit-tree; "$@"是一种完整地传递所有其他参数的方法,已经剥离了第一个shift.查看git help mktree和git help commit-tree获取信息.
所以,如果你需要多个级别,你必须嵌套一些额外级别的树对象(这不是测试但是一般的想法):
git filter-branch --commit-filter '
TREE="$1"
shift
SUBTREE1=`echo -e 040000 tree $TREE"\tbar" | git mktree`
SUBTREE2=`echo -e 040000 tree $SUBTREE1"\tb" | git mktree`
SUBTREE3=`echo -e 040000 tree $SUBTREE2"\ta" | git mktree`
git commit-tree $SUBTREE3 "$@"' -- --all
Run Code Online (Sandbox Code Playgroud)
这应该将实际内容转移到a/b/bar(注意相反的顺序).
更新:综合改进来自Matthew Alpert的答案如下.如果没有-- --all这个只适用于当前检出的分支,但由于问题是询问整个回购,因此以分支方式这样做更有意义.
And*_*ett 16
而不是创建一个新的存储库,将当前存储库中的内容移动到正确的位置:bar在当前目录中创建一个新目录并移动当前内容(因此您的代码所在/foo/bar/bar).然后baz在新bar目录(/foo/bar/baz)旁边创建一个目录. mv /foo /foo2; mv /foo2/bar /foo; rmdir /foo2你完成了:).
Git的重命名跟踪意味着您的历史记录仍然有用,而Git的内容散列意味着即使您已经移动了东西,您仍然会引用存储库中的相同对象.
这具体回答了“如何将我的 git 存储库移到一个或多个目录并使其看起来总是这样? ”
随着 的出现,git >= 2.22.0 git filter-repo可以利用它来重写历史记录,使其看起来好像父目录始终是其中的一部分。
这与@Walter-Mundt 的答案使用 完成的任务相同git filter-branch,但更简单并且执行起来不那么脆弱。
请注意,如今,它本身git filter-repo被宣传git filter-branch为更安全的替代方案。
因此,考虑到您的存储库位于/foo/bar/baz并且您希望将其移至/foo
首先,为了防止在重写历史记录时对工作区中的文件进行任何更改,请暂时将存储库变成所谓的“裸”存储库,如下所示:
cd /foo/bar/baz
git config --local --bool core.bare true
Run Code Online (Sandbox Code Playgroud)
现在可以直接在目录本身中完成实际的历史记录重写.git:
cd ./.git
git filter-repo --path-rename :bar/baz/
Run Code Online (Sandbox Code Playgroud)
这将重写存储库的完整历史记录,就好像每条路径总是预先添加bar/baz/到它之前(如果存储库的根目录向上两级,它们就会这样做)。此操作不会影响实际文件,因为现在这是一个裸存储库。
最后,再次将其打开,将.git目录移动到指定位置,然后重置:
git config --local --bool core.bare false
cd ..
mv ./.git ../..
cd ../..
git reset
Run Code Online (Sandbox Code Playgroud)
我认为,这git reset消除了存储库被裸露并再次返回的后遗症。git status在做之前尝试一下git reset看看我的意思。
现在,决赛git status应该证明一切都很好,模数一些新的未跟踪文件需要/foo/qux处理。
注意- 如果您在未克隆的存储库上尝试上述操作,git filter-repo将拒绝发挥其魔力,除非您--force...准备好备份并认为自己受到警告。
我有一个似乎没有人说过的解决方案:
我特别需要的是在我的存储库中包含父目录中的文件(有效地将repo移动到一个目录中).
我通过以下方式实现了
git mv)git add)git commit)的仓库中.我希望这有助于下一个人来 - 我可能只是一个没脑子的日子,但我发现上面的答案过于精细和可怕(我需要的东西.)我知道这与Andrew Aylett的答案类似,但我的情况似乎有点不同,我想要一个更普遍的观点.
这增加了Walter Mundt接受的答案.我宁愿评论他的答案,但我没有声誉.
所以Walter Mundt的方法效果很好,但它一次只适用于一个分支.在第一个分支之后,可能会有警告要求-f强制执行操作.因此,要立即为所有分支执行此操作,只需在末尾添加" - --all":
git filter-branch --commit-filter '
tree="$1";
shift;
subtree=`echo -e 040000 tree $tree"\tsrc" | git mktree`
git commit-tree $subtree "$@"' -- --all
Run Code Online (Sandbox Code Playgroud)
要为特定分支执行此操作,请将其名称添加到最后,尽管我无法想象为什么要更改某些分支的目录结构.
在git filter-branch的手册页中阅读更多相关信息.但是,请注意使用此命令后可能出现的困难警告.只要确保你知道你在做什么.
我对这种方法的任何潜在问题有更多的意见.
在大多数正常情况下,git使用相对于其位置(即.git目录)的所有文件,而不是使用绝对文件路径。
因此,如果您不介意历史记录中的提交表明您已将所有内容都向上移动,则有一个非常简单的解决方案,其中包括移动git目录。唯一有些棘手的事情是确保git理解文件是相同的,并且它们相对于他只是相对移动了:
# Create sub-directory with the same name in /foo/bar
mkdir bar
# Move everything down, notifying git :
git mv file1 file2 file3 bar/
# Then move everything up one level :
mv .git ../.git
mv bar/* .
mv .gitignore ../
# Here, take care to move untracked files
# Then delete unused directory
rmdir bar
# and commit
cd ../
git commit
Run Code Online (Sandbox Code Playgroud)
唯一要小心的是,在移至新目录时正确更新.gitignore,以避免暂存不需要的文件或忘记一些文件。
在某些设置中,当git看到与已删除文件完全相同的新文件时,git会自行找出文件已被移动。在这种情况下,解决方案甚至更简单:
mv .git ../.git
mv .gitignore ../.gitignore
cd ../
git commit
Run Code Online (Sandbox Code Playgroud)
同样,请小心您的.gitignore
| 归档时间: |
|
| 查看次数: |
10308 次 |
| 最近记录: |