Git工作流来审核提交而无需重写历史记录

时间:2014-04-08 15:53:29

标签: git git-workflow

我正在与一个刚接触git的开发人员合作,我想设置一个git工作流,让我审核这个开发人员提交的提交(并可能拒绝他们)而不强迫他改变他的工作(新用户容易出错。)

以下是该方案:

  • master分支仅包含经过审核的代码
  • devel分支是通过分叉master分支
  • 创建的
  • 开发人员正在devel分支机构上工作并推送他的代码供我审核
  • 我发现他的代码存在一些问题,所以我请他在devel分支上做更多提交以解决问题
  • 一旦我对代码感到满意,我就会挑选(或合并壁球)开发人员在master分支上提交,添加我自己的注释并将提交标记为开发人员编写的< / LI>
  • 开发人员将master分支合并回他的devel分支

以下是此方案的直观说明:

Visual scenario

在此序列之后,我怎样才能 100%确定开发人员在犯错误/重做过程中所犯的错误。当开发人员在其他一些提交后再次推送他的devel分支时,序列将不再显示

最好的解决方案是让开发人员将devel分支重新绑定到master分支,但这对新git用户来说是一项艰巨的任务。

如果这个工作流程有任何错误,请建议我另一个我可以在将它们合并到主分支之前审核提交的内容。

修改

一位朋友向我建议了一个看起来很有希望的方向:--fixup option做提交时。

  

--fixup=<commit>

     

构造用于rebase --autosquash的提交消息。提交消息将是指定提交的主题行,前缀为&#34; fixup! &#34 ;.有关详细信息,请参阅git-rebase

开发人员可以使用此选项将第二次和第三次提交正确标记为第一次提交。一个很好的解决方案...

7 个答案:

答案 0 :(得分:7)

备注1:尝试将devel上的单独提交转换为master上的单个提交, 重写历史记录。我看到了在master上保持干净,线性历史的重点,但是使用合并的线性历史记录更容易与git基本命令集成。

备注2:如果您的工作流程明确包含不熟悉您用来共享代码的基本工具的成员,那么您应该承担后果。在某些时候,我认为开发人员应该学习git。

以下是两条建议:

  1. 删除master上的线性历史记录,&#34;验证&#34;来自master的运行更改:

    git merge --no-ff devel
    

    这是告知git在devel上考虑master上的修改的最简单方法。

  2. 自己与devel合并,让开发人员从origin/devel中撤消修改。
    如果master上的单个提交实际上只包括压缩devel上的提交,这不应该触发任何冲突 - 合并提交master - &gt; devel应该引入0修改。
    如果您实际上已经修改了压缩的提交,开发人员可以对他自己进行本地修改,那么无论如何都必须面对触发冲突的可能性......

答案 1 :(得分:2)

如果您只是压缩dev分支而不是正常合并它,那么将那个压扁的提交合并回{{1}并不是一个好主意。分支,因为那时你会得到大量令人困惑的冲突,因为git认为你正在应用新代码,而实际上它实际上是相同的代码。

最好是简单地合并到dev,然后简单合并回master,否则扔掉devel分支并创建一个新分支最近提交的devel。根据您的说法,只要您合并到master的代码是&#34;好&#34;,那么您可能无法获得任何回归。

另一方面,如果你按照原来的计划合并压缩提交回master,那么 增加 你的机会由于冲突混乱,发生了回归。

更新

我删除了上面部分答案,因为我实际上刚刚测试了devel上的壁球提交,然后立即将其合并回master,并且它没有引起任何冲突,所以我答案的那部分是不正确的。

我把它变成了社区维基的答案,因为它在评论中仍然包含很多关于问题的信息。

答案 2 :(得分:2)

只需使用gerrit。使用gerrit,您将拥有您的评论,提交等历史记录。您也可以放弃更改。 我作为开发人员使用的工作流程:

准备

将gerrit commit-message hook复制到repo/.git/hooks。确保它是可执行的,并且不包含crlf。

如果您使用* nix,请使远程review推送或更好的shell别名。

在〜/ .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

挤压

当推向gerrit时,应该(可能)只有一次提交。

所以要将你的分支上的提交压缩成一个:

git reb

编辑器将打开。除了第一个(最早的提交)之外的每一行都将pick更改为squash。保存并退出。编辑器将打开提交消息。删除除最旧的提交消息之外的所有内容以及具有Commit-ID的行(gerrit需要它)。

衍合

如果合并你的分支在gerrit中失败,你可以将它重新定位到origin / master

git rebase origin/master

如果存在许多冲突,您可以通过使用cherry-pick

来避免解决其中许多冲突的痛苦
git checkout -b topic2 origin/master
git cherry-pick topic
git branch -D topic
git branch -m topic

git review

使用gerrit时,您还可以使用git review来简化某些操作。

答案 3 :(得分:0)

如果您确保您的其他开发人员始终从某个分支创建更改,例如develop,您可以使用主分支设置,例如:

掌握,发展

如果您的开发人员只从开发分支创建功能分支,他可以创建他想要的所有提交。然后,当你认为它准备就绪时,你可以挑选/改变并用它来做你的事情。功能分支被删除,确保重写的历史记录消失。

您的所有开发人员需要记住的是,每当他想要启动新功能时,都要从远程开发分支创建分支,而当您说要将某些内容合并到开发中时,不要触摸他的本地功能分支。

然后当它准备就绪时,他会在本地删除他的myfeature分支,当你合并/重新定位/樱桃选择他的好的变化进入你的开发时,你会远程删除它。

只有好的提交进入开发分支。您的开发人员像以前一样从开发中创建新的分支。

我认为一些基本的分支是开发人员应该知道的最少的。如果他不能改变/清理他的分支/提交,我认为你必须同意遵循某个工作流程。

可能并不完美,但也许是一种可能的工作流程。希望它有所帮助。

答案 4 :(得分:0)

最简单的方法是将devel分支中的更改合并到master中。您只需要定期使用master更新分支,这样您的分支就不会过于分散(取决于其他人正在处理的功能)。

如果您希望在master上进行一次修改。您可以将开发人员提交的内容重新绑定到一个提交中,然后将其提交给master。这会导致复杂化,因为您只能git push -f更新远程devel分支,如果您的开发人员不熟悉git,则更新其devel分支会很复杂。或者您要求他们删除该分支,然后使用新分支进行任何后续工作。

您需要根据是否要让开发人员的所有提交显示在日志中来决定继续选择哪个选项。最容易和最麻烦的方法就是简单地合并devel和master。

答案 5 :(得分:0)

我将测试以下工作流程,并告知您事情进展顺利。

的先决条件

  • 开发人员必须能够从命令行提交
  • 开发人员应该始终保持在同一个分支上,这样他就不必担心当前检出哪个分支
  • 开发人员从不必须解决影响他未编写代码的冲突
  • 开发人员永远不会处于可能失去对其工作树的本地修改的情况

工具

git commit--fixup option

  

<强> --fixup=<commit>

     

构造用于rebase --autosquash的提交消息。提交消息将是指定提交的主题行,前缀为“fixup!”。

带有--autosquash, --autostash and --interactive options

git rebase

  

<强> --interactive

     

列出即将重新定位的提交。让用户在变基之前编辑该列表。此模式也可用于拆分提交。

     

<强> --autosquash

     

当提交日志消息以“squash!...”(或“fixup!...”)开头,并且提交的标题以相同的...开头时,自动修改rebase的待办事项列表-i使得标记为压缩的提交在修改提交之后立即生效,并将移动的提交的操作从pick更改为squash(或fixup)。如果您使用git commit --fixup/--squash引用了早期的修正/壁球,请忽略后续的“fixup!”或“squash!”。

     

此选项仅在使用 - 交互式选项时有效。

     

如果默认情况下使用配置变量rebase.autosquash启用 - autosquash 选项,则此选项可用于覆盖和禁用此设置。

     

<强> --autostash

     

在操作开始之前自动创建临时存储,并在操作结束后应用它。这意味着您可以在脏工作树上运行rebase。但是,谨慎使用:成功重组后的最终存储应用程序可能会导致非平凡的冲突。

工作流

  1. 开发人员将master分支分支到devel分支。 fork point标有标记(例如version_1.1
  2. 开发人员在devel分支上工作和提交。工作完成后,他将他的分支推送到远程存储库,以便审核员可以查看和验证它。
  3. 审核员获取devel分支并查看代码。如果某些事情不正确,他会要求开发人员进行一些修改。
  4. 对于开发人员完成的每个修改,应使用以下命令提交更正: git commit --fixup <commit that was not OK>。比分支再次被推。
  5. 一旦审核员对完成的修改感到满意,开发人员必须重新设置他的分支,以便将所有修复提交压缩成一个漂亮且无错误的提交(其他无关的工作可能同时被提交)。
  6. GIT_EDITOR=: git rebase tags/version_1.1 --interactive --autosquash --autostash

    GIT_EDITOR=:用于避免显示由于--interactive选项而显示提交列表的编辑器。需要此选项才能使fixup提交自动重新排序。

    最后一步是再次推送devel分支(使用--force选项),以便审核员可以将其合并到master分支中。下一个devel fixup的rebase基础可能是主分支或开发人员在合并回主分支后放在他的devel分支上的新标记。

    以下是生成的git树:

    gitk illustration of the fixup workflow

答案 6 :(得分:0)

好吧,如果您有一位初学者,并且您是唯一的审稿人,我建议您使用此工作流程:

  1. 开发人员从master创建本地分支以实现某些功能(分支名称:i-123)
  2. 开发人员将一些代码添加到分支机构i-123
  3. 开发人员创建合并请求以合并主分支上的i-123
  4. 审稿人发现了一些错误并将问题通知给开发人员
  5. 开发人员添加提交以解决问题并通知审阅者检查i-123分支的更改
  6. 审阅者验证源代码并接受合并请求(在主分支上合并i-123,因为结果i-123被销毁)
  7. 开发人员同步本地存储库(结果:主分支包含相对于i-123的更改,i-123被销毁)
  8. 开发人员可以继续执行第1步
  9. 这种方法允许一个开发人员同时处理一个或多个功能,并消除关于mantein更新开发分支的复杂逻辑。这对初学者来说很简单。