多文件改名签入的时候,在版本管理时是否有最佳实践?

36 views
Skip to first unread message

Zhao Quan

unread,
Aug 13, 2012, 2:42:46 AM8/13/12
to sh...@googlegroups.com
各位好,

我在实际工作中遇到这样一个情况。

由于项目是用于Code生成Code,所生成的Code是要在另一个项目中使用的。

但是,由于需求变化,以及设计变化等等的原因。

生成的结果相同的文件,文件名却不是每次都一样的。(当然,这是在控制中的)

但这样在签入版本管理工具的时候,就非常的让人头痛了。

因为,如果一次性删除之前生成的所有文件,那么文件的历史记录就荡然无存,就没法回滚了。

如果,人工去修改每一个文件在代码管理工具中的文件名,显然不太现实,所生成的文件数量还是很大的。

而,保留之前的文档,签入新的文件,那么次数一多,代码管理的文件数量又变得极其庞大。也不利于维护,降低可读性。

故,在此请教下,有没有好的最佳实践。

BTW,话说这个就是“版本控制是用来辅助写代码的。” 与“就是辅助配置管理工作。”之间的矛盾吧。

谢谢,

Felix Zhao

Zang MingJie

unread,
Aug 13, 2012, 2:45:48 AM8/13/12
to sh...@googlegroups.com
// 因为,如果一次性删除之前生成的所有文件,那么文件的历史记录就荡然无存,就没法回滚了。

你用的什么垃圾版本管理工具,竟然有这种奇葩的限制?!

Zhao Quan

unread,
Aug 13, 2012, 2:53:11 AM8/13/12
to sh...@googlegroups.com
这个原本的文件删除后,也没有建立和新文件的关联,
所以,这样。
当然,通过改名等方式建立关联也成,但正如我提到的,文件有点多。
这个不知是否我使用方法有误

2012/8/13 Zang MingJie <zealo...@gmail.com>

--
-- You received this message because you are subscribed to the Google Groups Shanghai Linux User Group group. To post to this group, send email to sh...@googlegroups.com. To unsubscribe from this group, send email to shlug+un...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/shlug?hl=zh-CN
 
 

Ben Luo

unread,
Aug 13, 2012, 3:12:53 AM8/13/12
to sh...@googlegroups.com
还是先说用什么版本管理软件吧。这种空对空的谈没意义。

2012/8/13 Zhao Quan <felix...@gmail.com>

依云

unread,
Aug 13, 2012, 3:28:48 AM8/13/12
to sh...@googlegroups.com
肯定不是用的 git 就是了。git 才不管你是怎么重命名的,它发现内容比较像就
会把相关文件标记成重命名。

On Mon, Aug 13, 2012 at 03:12:53PM +0800, Ben Luo wrote:
> 还是先说用什么版本管理软件吧。这种空对空的谈没意义。
>
> 2012/8/13 Zhao Quan <felix...@gmail.com>
>
> > 这个原本的文件删除后,也没有建立和新文件的关联,
> > 所以,这样。
> > 当然,通过改名等方式建立关联也成,但正如我提到的,文件有点多。
> > 这个不知是否我使用方法有误
> >
> > 2012/8/13 Zang MingJie <zealo...@gmail.com>
> >
> >> // 因为,如果一次性删除之前生成的所有文件,**那么文件的历史记录就荡然无存,就没法回滚了。
> >>
> >> 你用的什么垃圾版本管理工具,竟然有这种奇葩的限制?!
> >>
> >>
> >> On Monday, August 13, 2012 2:42:46 PM UTC+8, Felix Zhao wrote:
> >>>
> >>> 各位好,
> >>>
> >>> 我在实际工作中遇到这样一个情况。
> >>>
> >>> 由于项目是用于Code生成Code,**所生成的Code是要在另一个项目中使用的。
> >>>
> >>> 但是,由于需求变化,以及设计变化等等的原因。
> >>>
> >>> 生成的结果相同的文件,文件名却不是每次都一样的。(当然,**这是在控制中的)
> >>>
> >>> 但这样在签入版本管理工具的时候,就非常的让人头痛了。
> >>>
> >>> 因为,如果一次性删除之前生成的所有文件,**那么文件的历史记录就荡然无存,就没法回滚了。
> >>>
> >>> 如果,人工去修改每一个文件在代码管理工具中的文件名,**显然不太现实,所生成的文件数量还是很大的。
> >>>
> >>> 而,保留之前的文档,签入新的文件,那么次数一多,**代码管理的文件数量又变得极其庞大。也不利于维护,降低可读性。
> >>>
> >>> 故,在此请教下,有没有好的最佳实践。
> >>>
> >>> BTW,话说这个就是“版本控制是用来辅助写代码的。” 与“就是辅助配置管理工作。”之间的矛盾吧。
> >>>
> >>> 谢谢,
> >>>
> >>> Felix Zhao
> >>>
> >> --
> >> -- You received this message because you are subscribed to the Google
> >> Groups Shanghai Linux User Group group. To post to this group, send email
> >> to sh...@googlegroups.com. To unsubscribe from this group, send email to
> >> shlug+un...@googlegroups.com. For more options, visit this group
> >> at https://groups.google.com/d/forum/shlug?hl=zh-CN
> >>
> >>
> >>
> >
> > --
> > -- You received this message because you are subscribed to the Google
> > Groups Shanghai Linux User Group group. To post to this group, send email
> > to sh...@googlegroups.com. To unsubscribe from this group, send email to
> > shlug+un...@googlegroups.com. For more options, visit this group at
> > https://groups.google.com/d/forum/shlug?hl=zh-CN
> >
> >
> >
>
> --
> -- You received this message because you are subscribed to the Google Groups Shanghai Linux User Group group. To post to this group, send email to sh...@googlegroups.com. To unsubscribe from this group, send email to shlug+un...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/shlug?hl=zh-CN
>
>

--
Best regards,
lilydjwg

Linux Vim Python 我的博客:
http://lilydjwg.is-programmer.com/
--
A: Because it obfuscates the reading.
Q: Why is top posting so bad?

Zhao Quan

unread,
Aug 13, 2012, 3:39:50 AM8/13/12
to sh...@googlegroups.com
奥我,现在项目中使用的是TFS。

Git如此神奇?

文件本身内容也有被更新,不仅仅是名称更改呢。

2012/8/13 依云 <lily...@gmail.com>

Liu Cheng

unread,
Aug 13, 2012, 3:46:47 AM8/13/12
to sh...@googlegroups.com
git根本不管diff的,就是同一个文件改一点就是存一个新文件

2012/8/13 Zhao Quan <felix...@gmail.com>:

Zhao Quan

unread,
Aug 13, 2012, 4:18:05 AM8/13/12
to sh...@googlegroups.com
在该文件的名称和内容都有修改后git是如何处理的呢?

BTW,就当前这个情况,大家有什么建议。

不如操作步骤的建议哈。

2012/8/13 Liu Cheng <ccp...@gmail.com>

唐嘉祺

unread,
Aug 13, 2012, 6:33:26 AM8/13/12
to sh...@googlegroups.com

版本库管理,是不是可以浏览历史版本的。我是用svn的。

--

依云

unread,
Aug 13, 2012, 7:17:31 AM8/13/12
to sh...@googlegroups.com
On Mon, Aug 13, 2012 at 04:18:05PM +0800, Zhao Quan wrote:
> 在该文件的名称和内容都有修改后git是如何处理的呢?
>
> BTW,就当前这个情况,大家有什么建议。
>
> 不如操作步骤的建议哈。

它会以某种我还不理解的方式比较文件内容。文档上说会有损性能但是我没有感觉
到。

操作步骤嘛:

rm -r *
generate_new_code
git add .
git ci -m 'update code'

显示提交 stat 的时候,会有 dir/{a => b} ++ 97% 这样的提示的。

不过可能某些情况下默认不会进行重命名的检测,加上 -M 选项就可以了。另外,
检测复制的选项是 -C。

以下是一个示例,我更改了文件名后又从文件中删除了三行文本:

>>> git diff --staged -M --stat
filetype.vim => a | 3 ---
1 file changed, 3 deletions(-)

Bojie Li

unread,
Aug 13, 2012, 12:48:22 PM8/13/12
to sh...@googlegroups.com
2012/8/13 依云 <lily...@gmail.com>:
> 它会以某种我还不理解的方式比较文件内容。文档上说会有损性能但是我没有感觉
> 到。
>
从git源码看,检测文件rename的算法是:

1.与HEAD指向的commit对应的tree进行比较,如果同路径文件已经存在,则无论进行了多大的修改,它都不会被看作是另一个文件的rename。

2.如果没有找到,则首先判断这是不是100%相同的重命名。在上一提交中找到所有SHA1值相同的文件,如果有多个则尽可能选用没有被本次重命名检测过程使用过,或者文件名相同(即目录变化)的文件。

3.如果没有找到,则需要判断这是修改后又重命名的文件,还是一个“全新”文件。这需要扫描上一提交中的所有文件。如果新建文件个数与原有文件个数之积(这是扫描算法的复杂度)超过了rename_limit的平方(默认为32767,可用merge.renameLimit配置),则在加入-C选项时进入“降级模式”,而默认情况下不进行重命名检测。

对每个原有文件与新建文件的“对子”计算相似度(见分割线下),只有相似度大于50%的对子才能入“法眼”;对每个新文件,只保留相似度最高的4个对子。待所有对子的相似度计算完毕后,将对子按照相似度从大到小排序,再一个个地把对子挑出来,当然已经配对的文件不能再配对了(这也是保留4个对子而不是最相似的一个的原因);如果配置成检测复制而不只是重命名的话,再运行一遍挑对子的过程。

4.所有新文件和原有文件被归类为rename、copy、create和delete,进行输出。

===============================
两个文件的相似度是一个0到MAX_SCORE(60000)的整数。首先,文件的大小不能相差太多。如果文件大小的差值>(MAX_SCORE-minimum_score)/MAX_SCORE*文件大小的较小者,则相似度为0。不然,相似度=两文件的相同字符数*MAX_SCORE/文件大小的较大者。

对文件的每行(如果超过64个字符则每64个字符一段)计算hash值,使用的是PJWhash的变体。将每个文件的这些hash值(每个hash值有一个字符个数计数器)排序,以便比较。每个文件只需要在第一次比较的时候读取文件并计算hash,以后直接用hash就行了。

比较两个文件其实就是比较两个文件各行的hash。由于hash是排序过的,因此类似归并排序中合并两个有序表的做法,扫描一遍,将hash值相同的行的字符数累加,即可获得两文件相同部分的字符数。不能不说这个算法很精巧。

Zhao Quan

unread,
Aug 13, 2012, 8:47:26 PM8/13/12
to sh...@googlegroups.com
感谢,分析十分详尽。将在此基础上对当前情况用Git做验证。

Zhao Quan

unread,
Aug 13, 2012, 8:48:35 PM8/13/12
to sh...@googlegroups.com
感谢我将尝试

Zhao Quan

unread,
Aug 15, 2012, 4:26:07 AM8/15/12
to sh...@googlegroups.com
我根据各位的建议用Git进行了如下尝试,
但结果并不是如想象中的那样。

请教下大家,对于这样的场景,有没有什么好的处理方式,或是流程。(最佳实践什么的)

场景:
  - 应生成code的需求,生成的文件内容和文件名会不断变化(其实,还是同一个文件)
  - 文件内容变动不会超过10%
  - 文件名称的变动并不频繁
  - 生成后的文件要Checkin版本管理工具(并且,希望能过做到历史回滚)
  - 当前“实验”使用版本管理工具为Git version 1.7.11

说明:
   - 实际情况下,生成的文件量很大
   - 不希望,手动更名所有文件
   - 希望能够对更名后的文件和更名前的文件作为同一历史作回滚。

处理步骤:
  - 在实验目录下执行 git init
  - copy 实验文件 test.A.x 至实验目录(内容为 425行代码)
  - git add test.A.x
  - git commit test.A.x -m "init"
  - git status (正常)
  - 删除该文件
  - 修改原始文件
     - 移除5行代码
     - 文件改名为A.x
  - copy A.x至实验目录
  - git add A.x
  - git commit A.x -m "change_1"
  - git status (Changes not staged for commit: ... deleted: test.A.x

实验结果:
  - 当test.A.x被删除后,git自动标记为一个delete动作。
  - A.x 被认为是一个新的文件。

结论:
  - 一次全部删除,再添加,总是会被认为是新文件的。





2012/8/14 Zhao Quan <felix...@gmail.com>

Chaos Eternal

unread,
Aug 15, 2012, 4:41:00 AM8/15/12
to sh...@googlegroups.com

生成的代码会手工改么

Zhao Quan

unread,
Aug 15, 2012, 4:42:00 AM8/15/12
to sh...@googlegroups.com

生成后,就不再进行手工修改了。
2012/8/15 Chaos Eternal <chaose...@shlug.org>

Chaos Eternal

unread,
Aug 15, 2012, 4:44:10 AM8/15/12
to sh...@googlegroups.com

那生成的code就该ignore。

版本管理工具不应该管理自动生成的代码。
该管理的是源。

Zhao Quan

unread,
Aug 15, 2012, 4:54:38 AM8/15/12
to sh...@googlegroups.com
生成的Code有什么可行的管理方式么?

有没有好的建议。

2012/8/15 Chaos Eternal <chaose...@shlug.org>

林孟潇

unread,
Aug 15, 2012, 5:08:52 AM8/15/12
to sh...@googlegroups.com
应该留下来一个生成Code的指导文件(类似INSTALL的存在)就可以了,然后ignore掉生成的代码。

Zhao Quan

unread,
Aug 15, 2012, 5:14:27 AM8/15/12
to sh...@googlegroups.com
这个。。。
目的是把生成的Code也做版本管理哈
如何忽略的话,就没有意义啦

2012/8/15 林孟潇 <linm...@gmail.com>

David pulq

unread,
Aug 15, 2012, 5:22:57 AM8/15/12
to sh...@googlegroups.com
删除是git rm, 重命名是git mv,为什么这两个还不能满足你的要求?

2012/8/14 Zhao Quan <felix...@gmail.com>
感谢我将尝试
-- You received this message because you are subscribed to the Google Groups Shanghai Linux User Group group. To post to this group, send email to sh...@googlegroups.com. To unsubscribe from this group, send email to shlug+unsubscribe@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/shlug?hl=zh-CN



David pulq

unread,
Aug 15, 2012, 5:29:15 AM8/15/12
to sh...@googlegroups.com
PS:所有的版本管理软件都有delete/rename的功能的,你删掉或者重命名一个文件本身就是一个改动,这个本身就是个历史,为什么说历史荡然无存呢?

Liu Cheng

unread,
Aug 15, 2012, 5:45:56 AM8/15/12
to sh...@googlegroups.com
删除该文件那一步应该用 git rm

2012/8/15 David pulq <pulq...@gmail.com>:

>>>>> shlug+un...@googlegroups.com. For more options, visit this group at
>>>>> https://groups.google.com/d/forum/shlug?hl=zh-CN
>>>>>
>>>>>
>>>


> --
> -- You received this message because you are subscribed to the Google Groups
> Shanghai Linux User Group group. To post to this group, send email to
> sh...@googlegroups.com. To unsubscribe from this group, send email to

> shlug+un...@googlegroups.com. For more options, visit this group at
> https://groups.google.com/d/forum/shlug?hl=zh-CN
>
>

Zhao Quan

unread,
Aug 15, 2012, 5:54:37 AM8/15/12
to sh...@googlegroups.com
同意,但是当文件很多的时候,有什么好的方式实现么?
谢谢

2012/8/15 Liu Cheng <ccp...@gmail.com>

依云

unread,
Aug 15, 2012, 6:05:05 AM8/15/12
to sh...@googlegroups.com
On Wed, Aug 15, 2012 at 04:26:07PM +0800, Zhao Quan wrote:
> [...]
>
> 处理步骤:
> - 在实验目录下执行 git init
> - copy 实验文件 test.A.x 至实验目录(内容为 425行代码)
> - git add test.A.x
> - git commit test.A.x -m "init"
> - git status (正常)
> - 删除该文件
> - 修改原始文件
> - 移除5行代码
> - 文件改名为A.x
> - copy A.x至实验目录
> - git add A.x
> - git commit A.x -m "change_1"
> - git status (Changes not staged for commit: ... deleted: test.A.x
>
> 实验结果:
> - 当test.A.x被删除后,git自动标记为一个delete动作。
> - A.x 被认为是一个新的文件。
>
> 结论:
> - 一次全部删除,再添加,总是会被认为是新文件的。

你添加的文件和删除的文件处于不同的阶段:添加的文件已经通过 add 命令添加
到 index (staging area)了,但是删除的文件只是在工作区删除了。你应该
git rm test.A.x 告诉 git 在此次提交中你也要删除这个文件。然后用
git status --staged 查看将要提交的内容。

David pulq

unread,
Aug 15, 2012, 6:11:10 AM8/15/12
to sh...@googlegroups.com
有种东西叫script :-)

Bojie Li

unread,
Aug 15, 2012, 4:58:09 AM8/15/12
to sh...@googlegroups.com
2012/8/15 Zhao Quan <felix...@gmail.com>:

> 处理步骤:
> - 在实验目录下执行 git init
> - copy 实验文件 test.A.x 至实验目录(内容为 425行代码)
> - git add test.A.x
> - git commit test.A.x -m "init"
> - git status (正常)
> - 删除该文件

要用git rm才能从文件系统和暂存区里同时删掉这个文件。

> - 修改原始文件
> - 移除5行代码
> - 文件改名为A.x
> - copy A.x至实验目录
> - git add A.x
> - git commit A.x -m "change_1"
> - git status (Changes not staged for commit: ... deleted: test.A.x

commit的时候只把新的A.x文件提交进去了,删除的test.A.x还在版本库里,当然不会被认为是rename了。
Changes NOT staged for commit啊……

>
> 实验结果:
> - 当test.A.x被删除后,git自动标记为一个delete动作。

git不会“自动标记”,只是在执行status或者commit的时候才会扫描文件系统。commit是把暂存区变成HEAD,而不是直接将文件系统的当前内容放进版本库。

> - A.x 被认为是一个新的文件。
>
> 结论:
> - 一次全部删除,再添加,总是会被认为是新文件的。

用git add -A,可以把包括增删在内的所有变动全部包含进去,再试试。

Chaos Eternal

unread,
Aug 15, 2012, 8:48:19 AM8/15/12
to sh...@googlegroups.com

这个目的本身就是没有意义的。

机器生成的东西没必要上版本管理。

管俊明

unread,
Aug 15, 2012, 8:54:41 AM8/15/12
to sh...@googlegroups.com

只要对你原马管理,要回滚目标代码!就回滚源代码再重新生成一下,不行!?或者打标签?

Bojie Li

unread,
Aug 15, 2012, 9:18:08 AM8/15/12
to sh...@googlegroups.com
你这个生成code的过程是否是脚本自动化的?如果是的话,可以写个“工作目录/.git/hooks/post-update”脚本,在原始代码修改之后,只要commit到版本库,就自动执行生成code甚至编译、测试的过程。写一次脚本,节省若干次敲命令的时间。

如果非要对生成的code单独做版本控制的话,可以另建一个版本库,生成code后copy到它的工作目录下,并执行git add -A和git
commit(可以使用.git/COMMIT_EDITMSG重用本次提交的message)尽管我没用过,但理论上可以自定义一些commit
message的标记,指挥post-update脚本做不同的事情。

2012/8/15 Zhao Quan <felix...@gmail.com>:

Zhao Quan

unread,
Aug 15, 2012, 10:42:26 PM8/15/12
to sh...@googlegroups.com
恩,由于当前项目的一个Layer完全是code generate生成出来的。
可以说,生成的结果就是项目本身。
其他人,有的项目整个都是Code generate出来的。

所以,对这些生成的结果不做版本管理,有些不太可能。



2012/8/15 Bojie Li <boj...@gmail.com>

Chaos Eternal

unread,
Aug 15, 2012, 10:54:07 PM8/15/12
to sh...@googlegroups.com
你要做的是把"源"用版本管理起来。比如,bison的文件要管理,但是生成的.c文件就不要管了;再比如,c文件会在编译的过程中产生 .o
甚至.s文件,这种文件也没必要版本管理。这种文件应该是 make clean 的过程中要删除的。

还有,对于非自由软件,发布这种中间文件是完全可以的,但是自由软件则不行,自由软件必须发布 “源”。

你一直在说不可能,但是你的需求除去不合理性之外,也是不可能的。除非你改写你的中间层生成语法,将所有的文件操作用git相应的操作替代:比如用git
rename代替 unlink和create。
再进一步说,你一直声称中间文件的命名是随机的,这种蛋疼的行为本来就是设计成不兼容版本控制的。

如果你说你的"源"文件不是文本格式,不适合git, 那你要做的是找一个适合这种格式的插件。

最后,建议你把整个项目的背景跟大家说说,不要老是说不可能。

2012/8/16 Zhao Quan <felix...@gmail.com>:

Zhao Quan

unread,
Aug 15, 2012, 11:09:17 PM8/15/12
to sh...@googlegroups.com
嗯,当前的项目很简单。
就是根据数据库中的表定义,以及一些用户的设定(也是表)
生成,所需要的DAL层。

由于,有用户自定义设置的内容。
所以,生成出的一部分code名称和内容都是会变化的。

为什么,要对生成的结果进行版本管理呢?
因为,DAL是给用户使用的。
让他们每次需要回滚DAL层code的时候,都要先回滚生成工具,再进行生成部署。
这个有点困难。
特别是在量比较大,过程比较复杂的时候。



2012/8/16 Chaos Eternal <chaose...@shlug.org>

Liu Cheng

unread,
Aug 15, 2012, 11:18:19 PM8/15/12
to sh...@googlegroups.com
这个不需要什么最佳实践了吧,你每个版本生成的代码打个包存到什么文件服务器上都行,这完全是别的东西的产出,追踪变化什么的又没有意义。

2012/8/16 Zhao Quan <felix...@gmail.com>:

Zhao Quan

unread,
Aug 17, 2012, 1:56:31 AM8/17/12
to sh...@googlegroups.com
今天去找了本Git的书看了看,
发现rename 问题对任何一个版本管理工具都是一个难题啊。

2012/8/16 Liu Cheng <ccp...@gmail.com>

Zang MingJie

unread,
Aug 17, 2012, 3:21:37 AM8/17/12
to sh...@googlegroups.com
Git的rename就是rm再add,没任何区别

On Friday, August 17, 2012 1:56:31 PM UTC+8, Felix Zhao wrote:
今天去找了本Git的书看了看,
发现rename 问题对任何一个版本管理工具都是一个难题啊。

Zhao Quan

unread,
Aug 17, 2012, 5:21:20 AM8/17/12
to sh...@googlegroups.com
Git 会仅仅改变,hierarchy tree

--
Reply all
Reply to author
Forward
0 new messages