[英]Git workflow to audit commits without rewriting history
I am working with a developer that is new to git, and I would like to setup a git workflow that would let me auditing the commits made by this developer (and possibly reject them) without forcing him to rebase his work (which is error prone for new users). 我正在与一个刚接触git的开发人员合作,我想设置一个git工作流,让我审核这个开发人员的提交(并可能拒绝他们)而不强迫他改变他的工作(这很容易出错)对于新用户)。
Here is the scenario : 这是场景:
master
branch contains only audited code master
分支仅包含经过审计的代码 devel
branch is created by forking master
branch devel
分支是由分支master
分支创建的 devel
branch and push his code for me to audit devel
分支并推送他的代码供我审核 devel
branch to fix the issue devel
分支上做更多的提交以解决问题 master
branch, add my own comments and mark the commit as authored by the developer master
分支上提交,添加我自己的注释并标记由开发人员编写的提交 master
branch into his devel
branch master
分支合并回他的devel
分支 Here is a visual illustration of this scenario : 以下是此方案的直观说明:
After this sequence, how can I be 100% sure that mistakes made by the developer during the "make mistakes / redo" sequence will not show up again when the developer will push his devel
branch again after some other commits ? 在这个序列之后,如果开发人员在其他一些提交之后再次推送他的
devel
分支,我怎么能100%确定开发人员在“犯错误/重做”序列期间所犯的错误不会再出现?
The best solution would be to ask the developer to rebase his devel
branch against the master
one, but this is a hard task to new git users. 最好的解决方案是要求开发人员将他的
devel
分支与master
重新绑定,但对于新的git用户来说这是一项艰巨的任务。
If this workflow is wrong in any way, please suggest me another where I would be able to audit the commits before merging them into the master branch. 如果这个工作流程有任何错误,请建议我另一个我可以在将它们合并到主分支之前审核提交的地方。
EDIT 编辑
A friend suggested me a direction that looks promising : the --fixup option when doing commit. 一位朋友向我建议了一个看起来很有希望的方向:提交时的--fixup选项 。
--fixup=<commit>
Construct a commit message for use with
rebase --autosquash
.构造一个用于
rebase --autosquash
的提交消息。 The commit message will be the subject line from the specified commit with a prefix of "fixup! ".提交消息将是指定提交的主题行,前缀为“fixup!”。 See git-rebase for details.
有关详细信息,请参阅git-rebase 。
This option could be used by the developer to properly mark his second and third commits as a fix for his first one. 开发人员可以使用此选项将第二次和第三次提交正确标记为第一次提交。 A good solution to explore...
探索的好方法......
Remark 1: By trying to turn the separated commits on devel
into a single commit on master
, you are rewriting history. 备注1:通过尝试将
devel
上的分离提交转换为master
上的单个提交,您将重写历史记录。 I see the point in trying to keep a clean, linear history on master
, however a less linear history with merges would be more easily integrated with git basic commands. 我看到了尝试在
master
上保持干净,线性历史的观点,但是使用合并的较不线性的历史将更容易与git基本命令集成。
Remark 2: If your workflow explicitly includes members which are not familiar with the basic tools you use to share code, you should live with the consequences. 备注2:如果您的工作流程明确包含不熟悉您用于共享代码的基本工具的成员,那么您应该承担后果。 At some point, I think the developer should learn git.
在某些时候,我认为开发人员应该学习git。
Here are two suggestions : 这有两个建议:
Drop the linear history on master, and "validate" the changes by running, from master : 删除master上的线性历史记录,并通过从master运行来“验证”更改:
git merge --no-ff devel
This is the most straightforward way to inform git that the modifications on devel
are taken into account on master
. 这是告知git在
master
上考虑devel
上的修改的最直接的方法。
Do the merge with devel
yourself, and have your developer pull the modifications from origin/devel
. 自己
devel
合并,并让开发人员从origin/devel
提取修改。
If the single commit on master really only consists in squashing the commits on devel
, this shouldn't trigger any conflicts -- the merge commit master
-> devel
should introduce 0 modifications. 如果master上的单个提交实际上只包括压缩
devel
上的提交,这不应该触发任何冲突 - merge commit master
- > devel
应该引入0修改。
If you have actually modified the squashed commit, and the developer can have local modifications of his own, you have to face the possibility of triggering conflicts on his side anyway ... 如果你实际上修改了压扁的提交, 并且开发人员可以对他自己进行本地修改,那么无论如何你都必须面对触发冲突的可能性......
If you're going to just squash the dev
branch instead of merging it normally, it's not a good idea to then merge that squashed commit back into the dev
branch, because then you'll get a ton of confusing conflicts, because git thinks you're applying new code, when in fact it's actually the same code. 如果你只是压缩
dev
分支而不是正常合并它,那么将那个压扁的提交合并回dev
分支并不是一个好主意,因为那样你会得到大量令人困惑的冲突,因为git认为你正在应用新代码,实际上它实际上是相同的代码。
It would be better to either just do a simple merge into master
, then a simple merge back into devel
, or otherwise throw-away the devel
branch and make a new one off of the most recent commit of master
. 最好是简单地合并到
master
,然后简单地合并回devel
,或者抛弃devel
分支并从最近的master
提交中创建一个新的。 As long as the code that you merge into master
is "good", according to you, then you probably won't get any regressions. 根据你的说法,只要你合并到
master
的代码是“好的”,那么你可能不会得到任何回归。
On the other hand, if you go with your original plan of merging in squashed commits back into devel
, that will increase your chances of a regression occurring, because of the confusing conflicts. 另一方面,如果你按照原来的计划将压缩的提交合并回到
devel
,那么由于冲突的混乱,这将增加你发生回归的机会。
I deleted parts of my answer above because I actually just tested doing the squash commit on master
and then immediately merging it back into devel
, and it didn't cause any conflicts, so that part of my answer was incorrect. 我删除了上面部分答案,因为我实际上刚刚测试了对
master
进行了squash commit,然后立即将它合并回devel
,并且它没有引起任何冲突,因此我的部分答案是不正确的。
I turned this into answer into a community wiki because it still contains a lot of information about the problem in the comments. 我把它变成了社区维基的答案,因为它在评论中仍然包含很多关于问题的信息。
Just use gerrit. 只需使用gerrit。 With gerrit you will have the history of your comments, commits etc. You can also abandon change.
使用gerrit,您将拥有您的评论,提交等历史记录。您也可以放弃更改。 The workflow I use as a developer:
我作为开发人员使用的工作流程:
Copy gerrit commit-message hook to your repo/.git/hooks
. 将gerrit commit-message hook复制到
repo/.git/hooks
。 Make sure it's executable and doesn't contains crlf. 确保它是可执行的,不包含crlf。
Make remote review for pushing, or better shell alias if you work on *nix. 如果您使用* nix,请对推送或更好的shell别名进行远程审核 。
Make alias for rebasing in ~/.gitconfig (about fork-point ) 在〜/ .gitconfig(关于fork-point )中为rebase创建别名
[alias]
reb = !"git rebase -i $(git merge-base --fork-point origin/master HEAD)"
while unapproved do
git commit -a --amend
git push review
# reviewers comment, reject, approve etc.
# If rejected, I change commit as required, then
end
When pushing to gerrit there should (probably) be only one commit. 当推向gerrit时,应该(可能)只有一次提交。
So to squash commits on your branch into one: 所以要将你的分支上的提交压缩成一个:
git reb
Editor will open. 编辑将开放。 Change
pick
to squash
for every line except first (oldest commit). 除了第一个(最早的提交)之外,将每个行的
pick
更改为squash
。 Save and quit. 保存并退出。 Editor will open with commit messages.
编辑器将打开提交消息。 Delete everything except oldest commit message and the line with Commit-ID (it's needed for gerrit).
删除除最旧的提交消息之外的所有内容以及具有Commit-ID的行(gerrit需要它)。
If merging your branch fails in gerrit, you can rebase it onto origin/master 如果合并你的分支在gerrit中失败,你可以将它重新定位到origin / master
git rebase origin/master
If there are many conflicts, you can avoid pain of resolving many of them just by using cherry-pick 如果有很多冲突,你可以通过使用樱桃选择避免解决其中许多冲突的痛苦
git checkout -b topic2 origin/master
git cherry-pick topic
git branch -D topic
git branch -m topic
You can also use git review to simplify some operations when working with gerrit. 在使用gerrit时,您还可以使用git review来简化某些操作。
If you make sure your other developer always creates changes from a certain branch, say develop, you can have main branch setup that always exist for example: 如果您确保您的其他开发人员始终从某个分支创建更改,例如develop,您可以拥有始终存在的主分支设置,例如:
master, develop 掌握,发展
If your developer only creates feature branches from the develop branch he can create commits all he wants. 如果您的开发人员只从开发分支创建功能分支,他可以创建他想要的所有提交。 Then when you think it is ready you can cherry-pick/rebase and do your thing with it.
然后,当你认为它准备就绪时,你可以挑选/改变并用它来做你的事情。 The feature branch gets deleted making sure rewritten history is gone.
功能分支被删除,确保重写的历史记录消失。
All your developer needs to remember would be to create a branch from the remote develop branch everytime he wants to start a new feature and not touch his local feature branch when you say you're going to merge some stuff into your develop. 您需要记住的所有开发人员都需要在每次想要启动新功能时从远程开发分支创建分支,而在您说要将某些内容合并到开发中时不要触摸他的本地功能分支。
Then when it is ready he deletes his myfeature branch locally and you delete it remote when you've merged/rebased/cherry-picked his good changes into your develop. 然后当它准备就绪时,他会在本地删除他的myfeature分支,当你合并/重新定位/樱桃选择他的好的变化进入你的开发时,你会远程删除它。
Only the good commits go into develop branch. 只有好的提交进入开发分支。 Your developer creates new branch from develop like before.
您的开发人员像以前一样从开发创建新分支。
I think some basic branching is the least your developer should know. 我认为一些基本的分支是你的开发人员应该知道的最少。 If he cannot rebase/clean his branch/commits I think you have to agree to follow a certain workflow.
如果他不能改变/清理他的分支/提交,我认为你必须同意遵循某个工作流程。
Maybe not perfect, but perhaps a possible workflow nonetheless. 也许并不完美,但也许是一种可能的工作流程。 Hope it helps.
希望能帮助到你。
The easiest way with the least amount of fuss would just be to merge in the changes from the devel branch into master. 最简单的方法是将devel分支中的更改合并到master中。 You just need to regularly update the branch with master so that your branches don't diverge too wildly (depending on what features other people are working on).
您只需要定期使用master更新分支,这样您的分支就不会过于分散(取决于其他人正在处理的功能)。
If you want to have one single commit for the modification on master. 如果您希望在master上进行一次修改。 You can rebase the developers commits into one single commit and then cherry-pick that commit onto master.
您可以将开发人员提交的内容重新绑定到一个提交中,然后将其提交给master。 This would lead to complications as you would only be able to do
git push -f
to update the remote devel
branch and if your developer is not familiar with git would be complicated for updating their devel
branch. 这会导致复杂化,因为您只能执行
git push -f
来更新远程devel
分支,如果您的开发人员不熟悉git,则更新其devel
分支会很复杂。 Or you would require that they delete that branch and then use a new branch for any future work. 或者您要求他们删除该分支,然后使用新分支进行任何后续工作。
You will need to decide which option to go on based on whether or not you want to have all the commits from your developer showing up in the log. 您需要根据是否要让开发人员的所有提交显示在日志中来决定继续选择哪个选项。 The easiest and least troublesome way is just to simply merge devel and master.
最简单,最麻烦的方法就是简单地合并devel和master。
I will test the following workflow and let you know if things are going well. 我将测试以下工作流程,并告知您事情进展顺利。
git commit
with the --fixup option : git commit
使用--fixup选项 git commit
:
--fixup=<commit>
Construct a commit message for use with
rebase --autosquash
.构造一个用于
rebase --autosquash
的提交消息。 The commit message will be the subject line from the specified commit with a prefix of "fixup! ".提交消息将是指定提交的主题行,前缀为“fixup!”。
git rebase
with --autosquash, --autostash and --interactive options git rebase
with --autosquash, - autostash和--interactive options
--interactive
Make a list of the commits which are about to be rebased.
列出即将重新定位的提交。 Let the user edit that list before rebasing.
让用户在变基之前编辑该列表。 This mode can also be used to split commits.
此模式也可用于拆分提交。
--autosquash
When the commit log message begins with "squash! ..." (or "fixup! ..."), and there is a commit whose title begins with the same ..., automatically modify the todo list of rebase -i so that the commit marked for squashing comes right after the commit to be modified, and change the action of the moved commit from
pick
tosquash
(orfixup
).当提交日志消息以“squash!...”(或“fixup!...”)开头,并且有一个提交标题以相同的...开头时,自动修改rebase -i的待办事项列表标记为压缩的提交在修改提交之后立即生效,并将已移动提交的操作从
pick
更改为squash
(或fixup
)。 Ignores subsequent "fixup! " or "squash! " after the first, in case you referred to an earlier fixup/squash withgit commit --fixup/--squash
.在第一个之后忽略后续的“fixup!”或“squash!”,如果您使用
git commit --fixup/--squash
引用了早期的fixup /git commit --fixup/--squash
。This option is only valid when the --interactive option is used.
此选项仅在使用--interactive选项时有效。
If the --autosquash option is enabled by default using the configuration variable
rebase.autosquash
, this option can be used to override and disable this setting.如果默认情况下使用配置变量
rebase.autosquash
启用--autosquash选项,则此选项可用于覆盖和禁用此设置。
--autostash
Automatically create a temporary stash before the operation begins, and apply it after the operation ends.
在操作开始之前自动创建临时存储,并在操作结束后应用它。 This means that you can run rebase on a dirty worktree.
这意味着您可以在脏工作树上运行rebase。 However, use with care: the final stash application after a successful rebase might result in non-trivial conflicts.
但是,谨慎使用:成功重组后的最终存储应用程序可能会导致非平凡的冲突。
master
branch into a devel
branch. master
分支分成一个devel
分支。 The fork point is marked with a tag (for exemple version_1.1
) version_1.1
) devel
branch. devel
分支上工作和提交。 When the work is done, he pushes his branch on the remote repository so that the auditor can see and validate it. devel
branch and look at the code. devel
分支并查看代码。 If something is not correct, he asks the developer to make some modifications. git commit --fixup <commit that was not OK>
. git commit --fixup <commit that was not OK>
。 Than the branch is pushed again. GIT_EDITOR=: git rebase tags/version_1.1 --interactive --autosquash --autostash
. GIT_EDITOR=: git rebase tags/version_1.1 --interactive --autosquash --autostash
。
The GIT_EDITOR=:
is here to avoid to display the editor that present the commit lists due to the --interactive
option. GIT_EDITOR=:
这里是为了避免显示由于--interactive
选项而出现提交列表的编辑器。 This option is needed to make the fixup
commit reorder automatically. 需要此选项才能使
fixup
提交自动重新排序。
The last step is to push the devel
branch again (with --force
option) so that the auditor can merge it in the master
branch. 最后一步是再次推送
devel
分支(使用--force
选项),以便审计员可以将其合并到master
分支中。 The rebase base for next devel fixup could be the master branch or a new tag that the developer put on his devel branch after merging back the master branch. 下一个devel fixup的rebase base可以是主分支或开发人员在合并回master分支后放在他的devel分支上的新标记。
Here is the resulting git tree : 这是生成的git树:
Well, if you have one beginner developer and you are the only reviewer, i suggest this workflow: 好吧,如果你有一个初学者开发者并且你是唯一的评论者,我建议这个工作流程:
This approach allow that one developer work on one or various features at same time, and eliminate complicate logic about mantein updated develop branch. 这种方法允许一个开发人员同时处理一个或多个功能,并消除关于mantein更新开发分支的复杂逻辑。 It's easy approach to the beginner developer.
这对初学者开发者来说很简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.