1
JhZ7z587cYROBgVQ 2016-08-08 09:55:00 +08:00 1
新开一个仓库?(手动滑稽)坐等楼下大神给出答案
|
3
vitovan 2016-08-08 09:56:31 +08:00
rebase ?
|
4
vitovan 2016-08-08 09:57:07 +08:00
|
5
Yancey OP @vitovan rebase 不行。。 rebase 是当前的回到某个时间点或 commits 。 现在是要把某个时间点之前的丢掉
|
6
Yancey OP @vitovan sorry 看错,以为你说的 reset 。 rebase 是可以。但是一般服务器的仓库是一个裸仓库(没有工作目录), git rebase , git branch 命令都没法使用。。如果在本地操作,强推到服务端。所有分支都会混乱、、
|
7
lijianying10 2016-08-08 10:02:59 +08:00
删掉本地仓库然后
git clone --depth=6 https://xxxxxxx.git 看看这种行不行? |
8
mengzhuo 2016-08-08 10:07:08 +08:00 via iPhone
本地 gc 一次 减少空间
而且删 commit 很不可取啊 |
9
relaxgo 2016-08-08 10:12:29 +08:00 via Android
试试这个方案 [git 替换]( https://git-scm.com/book/zh/v2/Git-工具-替换)
|
10
Yancey OP @lijianying10 这种治标不治本啊。。
|
12
shenqi 2016-08-08 10:14:52 +08:00
既然都打算这样了,就直接那个新的仓库,旧的仓库随时能查看就行了。
|
14
forcecharlie 2016-08-08 10:18:41 +08:00
git clone --depth 会从最新的 commit 迭代回去,并不是完整的 repository ,一些额外的操作需要还原成完整的仓库, 在服务器上进行 git gc ---prune=now 可以一定程度的减小仓库体积. 一个思路是,扫描出 仓库中大文件提交时的 父 commit, 然后将分支强制设置为此 commit,即修改 .git/refs/heads/xxxx 的 commitid ,工作目录删除此大文件,然后创建提交,运行 git gc, 强制推送到服务器,服务器运行 git gc . 这样仓库的体积就可以减小了,这个实际上和 git rebase 类似,但不会丢失当前的 commit. 对于你的需求, git commit 的创建由父 commit 根 tree,提交者 提交信息等通过 sha1 创建,是链式的,牵一发而动全身. 所以你的不太好实现.
|
15
Yancey OP @vitovan 因为丢掉历史,会让从截断的地方到现在最新的 commit 的 ID 都改变,也就是相当于把所有的留下的 commits 都重新提交了一遍。 这个时候服务端和本地 commits 没有一个是能对应上的。强行 push 我们期望的效果是 服务端的 commits 和分支记录 都完全被更改过的本地 commits 替换掉。。但是 git 并不会这样。
|
16
Yancey OP @forcecharlie 对啊。截断的效果就是从截断到现在最新的 commits 所有的 SHA
|
17
Yancey OP |
18
kukat 2016-08-08 10:27:22 +08:00
~ du -sh .git
758M .git |
19
bjzhou1990 2016-08-08 10:28:37 +08:00
|
21
zzn 2016-08-08 10:30:15 +08:00
公开项目不应该修改已提交的 commit ,除非让全部人重新 clone
其实很好奇,究竟.git 是有多大? 怎么会有这种需求。。。 |
22
Yancey OP @bjzhou1990 我就是参考这个。如图的 git 结构,遇到问题是,因为截断点之前还有 commit 。会导致截断后除了 之后想要的 commit 线外。 branch1 branch2 不会被操作。保持原样。 分支混乱。。
|
23
Yancey OP @zzn 背景是这样。 最开始一个主工程。然后 clone 了好几份工程作为不同的库(这个点我们暂定位 date 点)。后来这些库往不同业务发展。所以想将 date 点之前的所有 commit 删除。毕竟后来分成不同库了, date 之前和这些库完全没有啥关系。。
|
24
vitovan 2016-08-08 10:35:52 +08:00
r#15 @Yancey 嗯,刚才想说 --force 来着,如果不能让别人都接受 rebase ,好像确实有些难办:
http://stackoverflow.com/questions/8939977/git-push-rejected-after-feature-branch-rebase `rebasing feature branches on master and force-pushing them back to remote repository is OK as long as you're the only one who works on that branch.` |
25
jianyunet 2016-08-08 10:36:55 +08:00 1
既然都已经是公开项目了,在服务器端删掉也必须强推到各客户端啊。最简单的办法还是开一个新仓库做个 rebase
|
27
bjzhou1990 2016-08-08 10:45:27 +08:00 1
@Yancey 用 git checkout --orphan 创建新分支,然后在新分支上开发,丢弃原始分支?
|
28
Yancey OP @bjzhou1990 恩。是个好办法。
我测试还是遇到问题 1. 在服务端。我自己测试的时候是通过 git init --bare 来建仓库的,所以服务端 git checkout --orphan 命令没法使用。。 2. 服务端进行操作后,所有的本地仓库都要克隆一遍。。 我考虑的办法。 假设我们要截断的点 hash 值为 1234abc 在服务端: echo 1234abc > info/grafts git filter-branch -- --all 以及后续删除 grafts 和 gc 操作 写个脚本让所有本地克隆的都执行。内容大概是 echo 1234abc > .git/info/grafts git filter-branch -- --all 删除 grafts git fetch --all 目的是让本地和服务端改变一模一样。这样本地的分支。没有 push 的 commits 都可以保留 还是遇到问题 在服务端; 执行 git filter-branch -- --all 之前要将所有的 1234abc 之前的分支都删除。 在本地 git filter-branch -- --all 执行的时候 origin/xx 这种分支也会被操作。总之结果很混乱。不是想要的效果 看来真的是无解啊。。 |
29
jason19659 2016-08-08 10:59:25 +08:00
删除之后别人的项目跟你的肯定不是一个项目了。
|
30
subpo 2016-08-08 11:08:53 +08:00
迷之需求
|
31
bjzhou1990 2016-08-08 11:21:33 +08:00
@Yancey 所有 git 操作都应该是本地修改然后提交服务器,不要直接在服务器端修改啊。另外 git filter-branch 里的--all 意思是修改所有分支和 tag ,可以单独指定分支的吧?建议看看 git filter-branch --help ,文档很详细
|
33
SpicyCat 2016-08-08 11:45:20 +08:00
我觉得在做这个操作之前,先要反思下你们对 git 的使用。单纯的 git 提交历史长不不会显著增加 git repo 的大小,一般发现 git repo 突然增大,都是误添加了大文件。
因为 git history 太长觉得影响效率是误解。有些大项目,上万的 commit ,太稀松平常了。 具体到你的需求,你想删掉某个时间点以前的 commit ,是肯定能做到的, git rebase -i 就可以。但是那样做以后,我估计你的项目就出错了,因为必然有些文件是在某个 commit 被加进来的,然后你把那个 commit 删除了,那以后某个 commit 要修改那个文件,会出什么现象我也不知道。总之这样做隐患很大。 更不用说你想改的是服务器,会影响所有人,真是要慎重。 另外推荐一款清理 git repo 的工具 https://rtyley.github.io/bfg-repo-cleaner/ 不过我一般是用它删除特定文件,可能不太符合你的需求。 |
34
Yancey OP @SpicyCat 因为是 android 项目。我查了下大文件, 基本是图片或 jar 包。这些图片或 jar 包经过迭代现在很可能已经不再使用了,但是还在仓库历史里面。所以.git folder 比较大。
看来这问题是无解了。 |
36
9hills 2016-08-08 12:07:00 +08:00
rebase 可以只合并某个范围内的 commit 。但是修改后需要约定下所有人,同时重新拉取
|
37
mrcode 2016-08-08 12:20:07 +08:00
可以试试 revert 他会生成一个新的提交, 来抵消掉你指定的提交的更改. 然后 git 垃圾回收就回收掉没用的那部分了
|
38
SpicyCat 2016-08-08 12:22:43 +08:00
@Yancey 那么解决问题的方法就是确定哪些图片文件或者 jar 不需要了,利用 bfg(就是我上个回复提到的清理工具)清理一下。 bfg 是把目标文件彻底从 git repo 里删除。
|
39
SpicyCat 2016-08-08 12:23:23 +08:00
当然,最好还是新建一个 repo ,保留原有 repo 。
|
40
fy 2016-08-08 13:38:57 +08:00
翻出一篇笔记:
git clone [email protected]:jfinal/jfinal.git git filter-branch --tree-filter 'rm -f WebRoot/WEB-INF/lib/*.jar' --tag-name-filter cat -- --all git push origin --tags --force git push origin --all --force |
41
skydiver 2016-08-08 14:13:37 +08:00 1
|
42
AnyOfYou 2016-08-08 14:23:06 +08:00
官方的用来管理 Android 源码下众多 git 仓库的 repo 工具, init 的时候可以指定 branch 。
这个 repo 实际就是一堆 python 脚本。 init 后到会把 subcmds 下载到本地。你可以看其 sync 的实现并修改。 |
43
AnyOfYou 2016-08-08 14:25:13 +08:00
另外, init 的时候可以直接指定 --depth 。
|
45
SourceMan 2016-08-08 15:21:30 +08:00
楼主没说规模,我这边几个 G 的算什么程度?
|
48
402124773 2016-08-08 17:05:38 +08:00
7.2G .git
也没见过提出这个需求。 哈哈 |
49
wweir 2016-08-08 18:50:42 +08:00
不知道是否有更直接的操作方式
只知道 squash 命令可以压缩大量 commit 为一个 结合楼主的需求,也许结合 rebase 可以实现相应功能。 我们这边的做法是,在下一次大重构之前,拷出所有有用的代码为一个新的 repo 。老代码就自己慢慢滚下去,直到成为一个历史档案 |
50
jimages 2016-08-08 22:56:46 +08:00
这笔记本太熟悉了。渡边本。
|
51
msg7086 2016-08-08 23:10:17 +08:00
修改历史一定会导致 commit hash 变动,亲你不会连这点知识都没有吧……
|
53
tinyproxy 2016-08-09 08:44:22 +08:00 via iPhone
@Yancey 一个建议,资源文件等大体积的不要入库,传到某云存储去,通过一个 configure 脚本下载回来就好了
|
54
yuankui 2016-08-09 08:51:46 +08:00
@lijianying10 这个方法不错~
|
55
mrsatangel 2016-08-09 09:40:21 +08:00 1
`root -> A -> B -> C -> newRoot -> D `
也就是想要将 newRoot 之前的 commit 对象全部删除。 在`.git/info/`下建立`grafts`文件,在其中输入`newRoot`对象的 SHA1 值,保存。此时使用`git log`命令应该只能看到`newRoot`的 commit 记录。 之后使用`git filter-branch`使这个新建的 root 生效. 注意,这个 chop 操作可能会导致出现一个新的 detached 的 branch ,为当前的这个 branch 新建一个临时的 branch:`git branch tmp`,然后将 tmp branch 推送到远程的 repo 里想要更新的 branch (如 master ):`git push <remoteRepoName> tmp:<remoteBranchName>`,此时远程 repo 里面的**<remoteBranchName>**已经将**newRoot**之前的所有 commit 对象删除。 |
56
Yancey OP @mrsatangel 感谢。你的方案可行。
我原本以为本地截断后,不能强行推送到远端。原来是可以的。 不过你提到 “为当前的这个 branch 新建一个临时的 branch:`git branch tmp`,然后将 tmp branch 推送到远程的 repo 里想要更新的 branch (如 master ):`git push <remoteRepoName> tmp:<remoteBranchName>`,此时远程 repo 里面的**<remoteBranchName>**已经将**newRoot**之前的所有 commit 对象删除。” 感觉这个 tem branch 是多余的吧。直接强推截断的 master 就可以的。 另外对你的答案补充下; 假如你有如下的分支结构图 现在想从"57dd13f even"这个点截断。保留这个点上面的所有分支和 commit 首先需要 git push origin :test 将 test 分支删除。也就是说截断点以下的所有都删除。 再者 将截断点以上的所有分支都在本地有追踪分支 git checkout -b new origin/new 之后就执行 “在`.git/info/`下建立`grafts`文件,在其中输入`newRoot`对象的 SHA1 值,保存。此时使用`git log`命令应该只能看到`newRoot`的 commit 记录。 之后使用`git filter-branch`使这个新建的 root 生效. ” 最后执行 将本地所有分支都强推到远端一遍。 本例就是 git push --force origin master:master 和 git push --force origin new:new 哦对了,还要删除 original 文件夹保存的临时记录 rm -r .git/refs/original/ 最后效果: 其实这样的好处还有一个就是,所有 clone 这个仓库的本地仓库都可以执行一个相同的脚本。这样就不用大家都重新 clone 了,本地的 branch 和没有推送的 commit 也可以保留。 不知道理解对不对。可以再讨论。 |