【问题标题】:Apply stash with untracked files already committed使用已提交的未跟踪文件应用存储
【发布时间】:2016-03-29 23:40:47
【问题描述】:

我被要求编写一个脚本以在 Visual Studio 的构建后事件中运行,该脚本将通过将所有更改(包括新的(未跟踪的)文件)提交到本地“自动提交”分支来响应输出更新构建.这个想法是为了帮助懒惰的开发人员经常备份可构建代码,这样他们就可以避免丢失他们的工作。

我目前的做法(见下面的 sn-p):

如果用户不在自动提交分支上,我会存储他们的更改和未跟踪的文件,签出自动提交分支,应用存储,然后提交,然后返回到上一个分支并从存储中弹出以返回初始状态.

我的问题:

如果文件在用户当前分支上未跟踪,但已自动提交到自动提交分支,则git stash apply 无法用存储中未跟踪的版本覆盖自动提交分支上跟踪的文件。

git stash documentation 看来,我似乎没有任何相关参数可以在apply 调用中使用来解决这个问题。我可以通过解析git status --porcelain?? 开头的行的结果,在存储之前检测当前分支中未跟踪的文件,但这不会告诉我哪些文件已经在自动提交分支上被跟踪。

我目前需要使用 Windows 批处理文件,因此我想将我的解决方案限制在任何开发机器上可能在该环境中可用的工具上。

这是我当前方法中的相关 sn-p:

git stash save --include-untracked -keep-index
git checkout autocommit
git stash apply
git add -A
git commit -m "Autocommit of build %VERSION%"
git checkout  %BRANCHNAME%
git stash pop

偏离 git 哲学

自动提交过程旨在严格用作一个方便的、基于 git 的自动保存系统,它不需要开发人员在每次成功重建项目时触摸 git 或采取任何额外的手动步骤。

它不符合普通的 git 哲学,因为它不打算用于源代码控制或代码共享。我只是想使用 git 为开发人员提供快照以恢复到例如如果他们因文件损坏而失去项目。这将导致大量微小的提交而没有什么个人价值,这没关系 - 事实上,它非常适合我的需求。

脚本假定当前分支上未提交的更改可以合理地应用并提交到自动提交分支。假设无效的任何原因都将由开发人员与 repo 的直接交互引起。作为任何此类交互的一部分,开发人员负责相应地更新自动提交分支,以便脚本的假设在下次运行时有效。

【问题讨论】:

  • 我确实意识到 cmets 说“不要这样做”是多么无益,但我强烈建议更好的选择是培训开发人员经常自己提交。这听起来像是会鼓励不良练习。另外,如果%BRANCHNAME% 的上游发生了某些变化,会发生什么情况?您需要先变基或合并您的 autocommit 分支,不是吗?
  • @DaveyDaveDave 一个有效的观点,我倾向于同意。在这种情况下,开发人员确实练习了良好的做法,他们还希望一些方便的自动化系统利用 git 功能通过高频率备份他们的本地工作以获得广泛的历史来帮助他们的个人工作流程。理想情况下,自动提交分支永远不会被合并到另一个分支中,或者实际上不会参与除自动提交过程和历史审查之外的任何操作。
  • 至于上游更改的影响,我假设开发人员会注意并以某种程度的智能管理自动提交分支的同步。除非有一个我没有考虑的细节(很可能 - 我不是 git 大师),否则我很满意忽略自动提交过程中的那一点复杂性。
  • 我在这里很可能错了,我必须对其进行测试才能确定,但​​假设autocommit 分支在提交C1 并且我继续master 将它带到C5,文件 foo 已更新。如果然后我自己更改foo 并尝试将其提交给autocommit,而不将C2 更改为C5,会不会有可怕的冲突?我必须承认我有偏见,因为在 90% 的情况下,git up 自动存储东西并出错,所以可能没有我想的那么糟糕......
  • @talrnu,每次提交都是一个小的有意义的更改会很有意义。如果只是很多零散的小改动,其实适得其反。好好想想吧!

标签: git git-commit git-stash post-build-event


【解决方案1】:

我发现您的方法存在一些潜在问题:

  1. git stash apply on autocommit 可能会产生需要手动解决的冲突。这将把“自动”排除在整个过程之外。
  2. autocommit 上的提交不能保证与当前工作副本相同,因为git stash apply 执行合并。

以下顺序应该可以解决这些问题并回避您的原始问题。

git stash -u
git stash apply
git add -A
git commit -m "dummy"
git merge --no-ff autocommit -s ours
git checkout autocommit
git merge - --squash
git commit -m "Autocommit of build %VERSION%"
git checkout -
git reset --hard HEAD~2
git stash pop

说明:

  1. 保存工作副本的当前状态。
  2. 恢复工作副本。
  3. 上演一切
  4. 在当前分支上进行虚拟提交。这将被复制到“自动提交”并随后从当前分支中删除。
  5. autocommit 与我们的更改合并,以方便移动更改。 ours 策略确保合并的结果与我们要保存的工作副本的状态相同。与此策略永远不会发生合并冲突。此合并无法在autocommit 中完成,因为没有theirs 策略。
  6. 移至autocommit 分支。
  7. 将更改带入分支。 --squash 选项至关重要。没有提交,而是暂存所有更改。
  8. 提交分阶段的更改。
  9. 后退。
  10. 删除虚拟提交和合并提交。
  11. 返回原始状态。

结果应该是在 autocommit 上的一次提交,代表工作副本。

请注意,此脚本可能会提交大量垃圾(构建文件)。 autocommit 分支对于不同的开发人员也会有很大的不同。我建议它保持本地化以避免使原始存储库膨胀。如果您必须推送它,请尝试为每个开发人员提供自己的分支名称以避免冲突。

【讨论】:

  • 很好,没想到这种方法,就像一个魅力。我根据测试结果对您的答案进行了一些小修改。是的,它仅供本地使用,尽管偶尔合并到每个开发人员的远程备份分支可能是可行的。谢谢!
  • 显然我的编辑被拒绝了,建议将它们作为 cmets 发布: 1. git reset --hard HEAD~2 必须是 ...HEAD~1,否则你最终会提交一个太远的结果。 2. 如果你没有正确配置.gitignore,你只会得到很多垃圾文件。使用好的 .gitignore,正如我测试和确认的那样,无论构建输出文件如何,此脚本都能完美运行。
  • @talrnu HEAD~2 可能是因为合并变成了快进合并。您应该尝试将--no-ff 添加到第一个合并中。
  • 我明白了,~2 在我的测试中失败了,因为我只是在测试第一个自动提交。那时,自动提交分支中的唯一提交已经在我的工作分支中,因此将其合并回我的工作分支根本不会做任何事情,因为没有要合并的更改。~1 有效,因为只有一个承诺在那时重置,但在自动提交发生后~2 工作正常。如果我运行自动提交然后立即提交到我的工作分支,我将在下一次自动提交时遇到同样的问题。关于如何处理的任何想法?
  • --no-ff 测试过,还是不行。我的测试从一个新的仓库开始,我添加了 3 个文件(和一个 .gitignore,配置为忽略其中一个)并创建第一个提交,创建自动提交分支,修改一些文件(第一阶段,保留一个未暂存,并创建一个新的未跟踪文件,忽略忽略的文件),然后手动运行脚本中当前显示的各个命令。自动提交过程中的第一次合并(使用--no-ff)会产生“已经是最新的”消息,并且不会发生合并。有道理——此时自动提交分支已经合并了。
猜你喜欢
  • 2017-12-30
  • 2011-02-27
  • 1970-01-01
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 2013-11-08
相关资源
最近更新 更多