繁体   English   中英

如何使用 git 完成与 mercurial 相同的工作流程?

[英]How can I use git to accomplish the same workflow I use with mercurial?

我是一个生活在 git 世界的 hg 女孩。 我有一个经常发生的通用工作流程,我似乎无法理解它应该如何在 git 中完成。 那么让我来描述一下我是如何使用 mercurial 进行管理的。

所以我从我的起源中拉出来,我有这 4 个提交

o  3:1f6b4172c41e
|
o  2:639ba9dc8afc
|
o  1:5bfb5ae3faf5
|
o  0:e0890b04d1d3

我开始黑客攻击并再进行 3 次提交,但我不会推动它们

o  6:e48cc97b3508
|
o  5:9a4c73cfb4f9
|
o  4:e32af117ea73
|
o  3:1f6b4172c41e
|
o  2:639ba9dc8afc
|
o  1:5bfb5ae3faf5
|
o  0:e0890b04d1d3

瞧,我发现我的新工作有问题。 我想重新开始,但不会失去我迄今为止所做的任何工作。 所以我发出命令让我回到 1f6b4

汞更新 1f6b4

o  6:e48cc97b3508
|
o  5:9a4c73cfb4f9
|
o  4:e32af117ea73
|
@  3:1f6b4172c41e
|
o  2:639ba9dc8afc
|
o  1:5bfb5ae3faf5
|
o  0:e0890b04d1d3

注意到 3 (1f6b4) 处的@ 这意味着下一次提交将从这一点开始。 所以假设我再提交三个提交,我的日志看起来像:

@  9:32001847b67a
|
o  8:fb7016a799d0
|
o  7:0269a427f0d9
|
| o  6:e48cc97b3508
| |
| o  5:9a4c73cfb4f9
| |
| o  4:e32af117ea73
|/
o  3:1f6b4172c41e
|
o  2:639ba9dc8afc
|
o  1:5bfb5ae3faf5
|
o  0:e0890b04d1d3

在这一点上我很高兴,我决定不再需要 4-6 变更集。 由于它们还没有被推送到我的中央存储库,我可以摆脱它们:

汞条 e32af

新的日志看起来像:(记住,hashcode 之前的修订 # 只是为了方便,就像 git 它的 hashcode 永远不会改变)

@  6:32001847b67a
|
o  5:fb7016a799d0
|
o  4:0269a427f0d9
|
o  3:1f6b4172c41e
|
o  2:639ba9dc8afc
|
o  1:5bfb5ae3faf5
|
o  0:e0890b04d1d3

现在我可以推送了,并且会发送 3 个新的提交。

我怎样才能在 git 中做到这一点? 这可以分解为两个问题:

  1. 我如何让 git“带我到 1f6b4”,以便工作目录包含这些文件,并且下一次提交将从这里分支。 通过分支,我不是指创建一个新分支,而是在现有分支上创建一个新头。 因此,如果我在 master 上工作并且头在 e48cc,我如何“转到”f16b4,即 3 个“祖先”提交回来,下一次提交将是直接后代并成为 master 分支上的新头?
  2. 一旦我决定不再需要提交和e32af的后裔,我怎么完全摆脱他们的? 我以为我之前摆脱了 git 中的东西,只是在我做类似git log --all类的事情时才看到它们。 这些提交只存在于这里,它们从未被推送过,我怎么能永远关闭它们?

现在可能有更好的方法在 git 中处理这个问题,我非常愿意学习它。 但是我真的很想知道如何完成这个“跳转到一个点”并从那里分支(最好不必创建新的分支名称)。

您所描述的内容在任何工作流程中都很常见,并且可以在具有不同分支的 git 中执行此操作,但如果您想坚持使用同一分支,则可能会很困难。

你会怎么做:

  • 到达提交 6 后,运行git branch new_branch_name <sha1-of-commit-3>
  • 添加提交 7、8、9
  • 推送 new_branch_name git push new_branch_name
  • 删除旧分支git branch -d old_branch_name

也可以复制与您描述的完全相同的流程,但也很容易搞砸。 这样做的方法是:

  • git rebase -i <sha1-of-commit-3>
  • 添加提交 7、8、9
  • git rebase --skip跳过其他提交。

...我真的很想知道如何完成这个“跳转到一个点”并从那里分支(最好不必创建新的分支名称)。

Git 可以做 Mercurial 可以做的事情,但是您必须创建一个新的分支名称。 问题是在 Git 中,分支名称没有任何意义。 它们没有任何语义。 它们可以随心所欲地添加、删除和更改。 它们实际上只有一个目的,那就是找到一些提交。

在 Git 中,提交同时发生在多个分支上。 对于习惯使用 Mercurial 的人来说,这从根本上来说很奇怪 但这是因为 Git 中的分支名称在某种意义上不是真实的。 (一段时间后,你就会习惯它。)Mercurial 与 Git 分支名称最接近的类比是 hg 书签。

Mercurial 中的分支名称是真实的东西:永恒不变的东西。 1一旦创建,您就无法真正更改 Mercurial 分支名称(除了像转换扩展这样的技巧之外)。 每个提交都在某个特定的分支上进行,一旦提交,就会在那个分支上,并且永远只在那个分支上。

相比之下,Git 提交只是进行了。 它们存在于一定数量的分支上:从零个分支到所有分支,同时存在。 那些允许您找到提交的分支名称被称为“包含”该提交。 分支名称的特别之处在于它可以是当前分支,当它是时,进行新提交会将新提交的 ID 推送到分支名称中。

我如何让 git“带我到 1f6b4”,以便工作目录包含这些文件,并且下一次提交将从这里分支。 通过分支,我不是指创建一个新分支,而是在现有分支上创建一个新头。

Git 没有头——或者,大多数情况下,一个分支名称就是一个头。

在 Mercurial 中,无论您是否能找到提交,都存在提交。 一旦完成,就存在提交。 如果提交根本没有后代,或者它的所有后代提交都在其他某个分支上——同样,Mercurial 提交只在一个分支上——那么该提交就是“头”。 因此,如果您列出所有头或当前分支中的所有头,您可以使用它们来查找所有提交或当前分支中的所有提交。

在 Git 中,没有“头”。 如果你找不到提交,它也可能不存在。 2可以直接找到的提交是那些具有名称的提交:分支名称、标签名称或任何其他名称。 您可以找到的其他提交是您可以直接找到的提交的祖先。

因此,为了能够找到提交1f6b4 ,您可以直接通过分支名称找到它,或者通过分支名称找到以后的提交,然后返回到1f6b4

所以:

git checkout -b newbranch 1f6b4

创建一个可以找到1f6b4的新名称 这并不能改变其分支机构的设置1f6b4是已经:它只是增加了一个分支1f6b4上。 作为1f6b4祖先的提交也在所有这些分支上,包括新的分支。

一旦我决定不再需要 e32af 的提交和后代,我该如何完全摆脱它们?

你没有。 相反,你删除分支名称(s)表示,导致e32af 现在你找不到它们,过了一段时间,会不时自动运行的3 git gc会吃掉它们。


1更准确地说,只要有提交,它们就会持续。 像 Git 一样,Mercurial 不能有分支名称,除非它有提交。

2有一些维护命令可以找到这样的提交,但是如果你没有足够快地运行它们并给它们附加名称,Git 的垃圾收集器git gc就会把它们扔掉。

3不可见提交的存活时间取决于:

  • gc.reflogExpire ,默认 90 天,用于从参考获得的提交; 或者
  • gc.reflogExpireUnreachable ,默认 30 天,用于无法从参考中访问的提交

这需要了解 Git 的 reflogs 的工作方式。 简而言之,这些提交的默认值为 30 天。 不过,自动 gc 仅在 Git 感觉gc.reflogExpireUnreachable时候运行:所以 30 天后,当gc.reflogExpireUnreachable将停止保护提交时,下一次自动 gc,无论何时实际运行,都会真正地剥离它们。

尽早移除它们是可能的,但几乎是非常困难的。 请注意,Git 不会备份已删除的提交,但只要您看不到它们,您就永远不会注意到它们的存在——除非它们有明显的副作用,例如持有 1 TB 的文件数据,或者其他什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM