软件重构的版本控制
进行大规模重构的版本控制的最佳方法是什么?
我典型的编程风格(实际上也是编写文档)是尽快得到一些东西,然后重构它。通常,重构与添加其他功能同时进行。除了类和函数的标准重构之外,函数还可以从一个文件移动到另一个文件,文件被拆分和合并或只是重新排序。
目前,我以单独用户的身份使用版本控制,因此现阶段不存在与其他开发人员交互的问题。尽管如此,版本控制给了我两个方面:
- 备份和“以防万一”恢复到良好版本的能力。
- 回顾历史可以告诉我项目是如何进展的以及想法的流动。
我在 Windows 上使用 Mercurial,使用 TortoiseHg,它可以选择要提交的帅哥。我提到这一点的原因是我想获得有关重构中提交粒度的建议。我是否应该将重构与始终在提交中添加的功能分开?
我已经查看了重构和源代码控制:如何?的答案,但是它没有回答我的问题。该问题重点关注与团队的协作。这个重点是拥有一个将来可以理解的历史(假设我没有像某些版本控制系统似乎允许的那样重写历史)。
What is the best way of doing version control of large scale refactoring?
My typical style of programming (actually of writing documents as well) is getting something out as quickly as possible and then refactoring it. Typically, refactoring takes place at the same time as adding other functionality. In addition to standard refactoring of classes and functions, functions may move from one file to another, files get split and merged or just reordered.
For the time being, I am using version control as a lone user, so there is no issue of interaction with other developers at this stage. Still, version control gives me two aspects:
- Backup and ability to revert to a good version "in case".
- Looking at the history tells me how the project progressed and the flow of ideas.
I am using mercurial on windows using TortoiseHg which enables selections of hunks to commit. The reason I mention this is that I would like advice on the granularity of a commit in refactoring. Should I split refactoring from functionality added always in committing?
I have looked at the answers of Refactoring and Source Control: How To? but it doesn't answer my question. That question focuses on collaboration with a team. This one concentrates on having a history that is understandable in future (assuming I don't rewrite history as some VCS seem to allow).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我想对于你的问题没有一个适合所有情况的答案:)
就我个人而言,我更喜欢在提交中保持更精细的合理粒度:在您的情况下,我会将操作分为两个阶段:每个阶段都是独立的:
最好的办法是单独添加和提交每个项目:分解本地更改中的重构,然后一项一项地提交它们,并一项一项地添加功能,并一路提交它们。
开销会多一些,但这样当您回去寻找差异时,就可以清楚重构哪些内容进行了更改以及添加新功能进行了哪些更改。仅回滚特定有问题的添加内容也更容易。
I suppose that there is no one size fits all answer to you question :)
Personally I prefer to keep the finer sensible granularity in my commits: in your case I would split the action in two phases: each one independent:
The best thing to do is to add and commit each item on its own: break up the refactoring in localized changes, and commit them one by one, and add the functionalities one by one, committing them along the way.
There is a little more overhead, but in this way when you go back seeking for differences it is clear what was changed for refactoring and what for adding new functionalities. It's also easier to rollback only a particular problematic addition.
我倾向于经常签到;每次签入要么是重构,要么是新功能。这是一个循环:
I tend to check-in frequently; and each check-in is either refactoring, or new functionality. It's a cycle of:
我建议将重构与添加功能分开。也许通过交替签到。这是我在发现 uncrustify 后的经验,并且会在更改代码的同时重新格式化源文件。仅仅通过重新格式化来找出真正的改变变得非常困难。现在,uncrustify 有了自己的专用提交。
I would recommend separating refactoring from adding functionality. Perhaps by alternating checkins. This is from my experiences after I discovered uncrustify and would reformat source files while also making code changes. It became very difficult to figure out a real change from just a reformat. Now uncrustify gets its own dedicated commits.
在处理了非常复杂的重构和相当广泛的更改的效果/错误/副作用的纠缠之后,我强烈建议您始终尝试尽可能地将两者分开。
如果出现任何问题,您可以非常轻松地从与每个阶段相关的标签/标签/版本重新构建代码,并验证两者中的哪一个引入了问题。
此外,尝试以尽可能小的逻辑完整块进行重构,并将它们作为单独的检查点提交。同样,这简化了对破坏原因/时间的调查。
Having dealt with untangling of effects/bugs/side effects of VERY complicated refactoring combined with fairly extensive changes, I can very strongly advise to always try to separate the two as far as your versioning, as much as possible.
If there are any issues, you can VERY easily re-build the code from the tags/labels/versions pertaining to each stage and verify which of the two introduced the issue.
In addition, try to do refactoring in as small as possible logically complete chunks and commit those as separate checkpoints. Again, this simplifies investigations into what broke why/when.
到目前为止,每个答案都建议您将重构与添加功能分开 - 并且我将它们全部+1。您应该独立于源代码控制来执行此操作。 Martin Fowler 围绕这样的概念写了一整本书:不能在不断变化的功能的同时进行重构。您想知道,对于任何更改,代码应该和确实在更改之前和之后的工作方式是否相同。正如 @Amardeep 指出的那样,如果通过格式化或重构更改来隐藏所做的功能更改,则很难看到所做的功能更改,因此更难追踪功能更改引入的错误。我这样说并不是要阻止您重构或推迟重构。一定要经常这样做。但要与功能更改分开进行。微提交是必经之路。
Every answer thus far has advised you to separate refactoring from adding functionality - and I +1'ed them all. You should do this, independent of source control. Martin Fowler wrote a whole book around the concept that you can't refactor simultaneously with changing functionality. You want to know, for any change, whether the code should and does work the same before the change as after. And as @Amardeep points out, it's much harder to see what functional change you have made if it's hidden by formatting or refactoring changes, thus much harder to track down bugs that functional changes introduced. I don't mean by this to discourage you from refactoring, or to postpone it. Do it, by all means, frequently. But do it separately from functional changes. Micro-commits are the way to go.
循序渐进。进行最小的有用更改,测试它,提交,然后重复。
一次一种改变。不要重构和改变行为
同一时间。
经常提交。带有清晰详细描述的小改动是非常宝贵的。
确保您的自动化测试可靠且有用。如果您可以信任您的测试,则可以轻松快速地完成上述操作。
确保您的测试始终通过。
通常我会开始研究新功能或错误修复或其他什么,发现如果我这样重构,新功能将更容易添加。通常我会放弃(或保存在其他地方)到目前为止的更改,重构/测试/提交,然后返回工作新功能。理想情况下,我花 90% 的时间进行重构,每个新功能、错误修复、性能改进等都是简单的单行更改。
Take baby steps. Make the smallest useful change, test it, submit, and repeat.
One kind of change at a time. Don't refactor and change behavior at
the same time.
Submit often. Small changes with clear, detailed descriptions are invaluable.
Make sure your automated tests are, reliable, and useful. If you can trust your tests, you can do the above easily and quickly.
Make sure your tests always pass.
Often I will start working on new functionality or a bug fix or whatever, to discover that if I refactor things just so, the new functionality will be much easier to add. Usually I will discard (or save elsewhere) my changes so far, refactor/test/submit, then go back to working the new functionality. Ideally I spend 90% of my time refactoring, and each new feature, bug fix, performance improvement, etc. is a simple, single-line change.