有没有办法在git日志中移动提交?

时间:2018-09-20 16:24:08

标签: git

我从另一个分支挑选了一个提交(不确定另一个分支是否相关),但是通过“ git log”显示它正在将该提交添加到历史记录的结尾/顶部,即使它具有进行提交的正确日期和时间。有没有办法将此提交移回日志,以便与其他提交相比,日期/时间有意义?

3 个答案:

答案 0 :(得分:1)

您可以重新设置基准并移动提交,但这是不可取的,特别是如果您已推动该仓库并与其他人一起工作,因为提交ID会发生变化,从而破坏所有引用。

评论者指出:

  • 如果您是在本地工作,那很好,而且
  • 提交对象实际上有两个日期。

如果您只关心提交顺序的“合理性”,则还可以使用rebase --committer-date-is-author-date来更改选择的提交的日期,从而最大程度地减少潜在的问题,因为您可能尚未推送此特定的提交。

答案 1 :(得分:1)

请小心您的要求。 git log说谎,但这是好事!

好的,“谎言”是夸大其词。但值得记住的是,git log向您展示了某物,但这是对现实的一个窥视孔,而不是一次看到所有现实。有点像time is nature's way of keeping everything from happening at oncegit log必须告诉您一次提交一个声明,但它们全部在那里。

提交

首先,提交具有两个时间戳,而不仅仅是一个。默认情况下,git log为您显示作者日期。 --since--until参数查看提交者日期。对于大多数提交,两个时间戳匹配,这无关紧要。对于精心挑选的提交,或与原始作者不同的人所做的提交,有时确实很重要。以下是git log --pretty=fuller的输出,显示了这样的提交:

commit 6c6ce21baa9b50d394bb8ed9878944504ffd57d8
Author:     Eric Sunshine <sunshine sunshineco.com>
AuthorDate: Fri Aug 31 04:33:42 2018 -0400
Commit:     Junio C Hamano <gitster pobox.com>
CommitDate: Fri Aug 31 12:05:24 2018 -0700

    config.mak.uname: resolve FreeBSD iconv-related compilation warning

    OLD_ICONV has long been needed by FreeBSD so config.mak.uname defines
    it unconditionally. However, recent versions do not need it, and its
    presence results in compilation warnings. Resolve this issue by defining

第二个(实际上可能更重要的是)每个Git提交都将其 parent 提交或多个提交的哈希ID作为其自身数据的一部分存储。这意味着提交具有父/子关系。任何Git提交的真实名称实际上就是它的丑陋的哈希ID,例如上面的6c6ce21...

我们可以使用git rev-parse或直接查看提交对象来找到提交的父项:

$ git rev-parse 6c6ce21baa9b50d394bb8ed9878944504ffd57d8^1
53f9a3e157dbbc901a02ac2c73346d375e24978c
$ git cat-file -p 6c6ce21baa9b50d394bb8ed9878944504ffd57d8
tree 1832fd8f6315732daca5c0523a951d40a8ee7fb2
parent 53f9a3e157dbbc901a02ac2c73346d375e24978c
author Eric Sunshine ...[snip]

父/子关系仅通过以下parent行定义:所有提交都会被冻结,并且在您提交时,它有其父级,但是还没有子级 。由于您在提交后无法更改提交,因此父级无法记住其子级。但是父母存在,所以孩子可以记住父母。

让我们画一条简单的提交行,为它们提供一个字母名称,而不是一个大的丑陋的哈希ID,其中每个提交都有一个父对象和一个孩子,但第一个或 root 提交除外(没有父项)和没有子项的最后一次提交或 tip 提交:

A  <-B  <-C  <-D  <-E  <-F  <-G

如果我们从末尾开始(Git通常会这样做),那么我们手中就有了G。因此,git log开始前进,从它现在正在进行的提交开始,并显示提交GG记住了F的丑陋哈希值大,因此现在git log向后退一步并显示F;然后它再次前进到ED,依此类推,直到到达A。我们说每个提交指向指向其父级,而Git遵循这些指针。

Git的真正诀窍是它以某种方式找到了G。该图中没有指向指向 G的东西,那么Git如何找到它?答案是:分支名称。我们有一个分支名称,例如master,指向提交G

A--B--C--D--E--F--G   <-- master

由于提交被冻结,而且我有点懒,:-)我放下了内部箭头。我们知道它们都指向后方,因此我们不需要它们:线条可以。 名称 master使Git可以找到提交G。 Git从G回到F,然后回到E,依此类推。

最有趣的事情是,当我们添加一个 new 提交时。假设我们git checkout master,以便我们提取了G个提交。然后,我们做一些工作并运行git addgit commit。这会产生一个 new 提交,带有一个新的大的丑陋哈希ID,但是我们将其称为HH将指向,即包含提交G的丑陋的哈希ID:

...--G   <-- master
      \
       H

Git做的最后一件事是将H的哈希ID写入名称master,这样master现在指向H(我们可以绘制直线再次直线):

...--G--H   <-- master

这意味着提交永不更改(它们不能更改),但是分支名称始终更改! Git更改的不是提交,而是提交,名称

分支和合并及其对git log

的影响

好的,所以我们有一些不错的直接历史提交行,但是现在当我们创建一些分支然后合并它们时会发生什么呢?答案是,Git进行合并提交,而这些提交只是两个父母的提交:

          I--J   <-- branch-A
         /
...--G--H
         \
          K--L   <-- branch-B

如果我们让Git合并了两者,我们将得到一个新的提交M,它同时具有 J L它的父母:

          I--J
         /    \
...--G--H      M
         \    /
          K--L

(练习:我将所有分支名称都放在这里。Git更新哪个分支名称?当有两个名称branch-Abranch-B时,Git怎么知道,哪个分支是您正在从事的工作?解决本练习将教给您很多有关Git的知识,或者通过下面提到的网站作弊::-))

现在,当git log前进时,它将显示提交M,但是随后-接下来应该显示哪个提交,JL

它需要同时显示 个提交。理想情况下,它应该同时显示它们,但不能。它必须选择一个才能显示。 (时间阻止一切立即发生。)这是时候(也是为什么)git log 必须撒谎:即使J和{{ 1}}实际上是“同时”在L之前。

在这里,M有一堆标记来告诉它如何撒谎。默认的谎言是使用您想要的东西:日期戳!但这是git log 默认显示的日期戳,即此处的提交日期。添加git log使Git选择作者日期而不是提交者日期。请注意,这仅会在--author-date-order具有现在要显示的多个提交时影响选择-当显示git log而不是{{1}时,这是正确的}。完成此操作后,它的 still 有两个提交要显示,即JL。它将使用您的排序选项从这两个中选择一个,然后再次显示两个提交:ILHL,具体取决于它刚刚显示了哪一个。

这太复杂了

是的,是的。不幸的是,这是现实。有一种方法可以使I使用K 绘制图形并显示提交。并非总是有帮助,但是当有帮助时,它非常有用

有关(更多)更多信息,请访问网站Think Like (a) Git。您需要知道这些东西,最终还是要有效地使用Git。不过,在此之前,git log的存在(默认情况下隐藏了所有这些复杂性)是一件好事。

答案 2 :(得分:0)

我不认为有。但这应该是一件好事。请记住,在“ git log”或修订历史记录中,它描述了协作者对存储库所做的工作。实际上,'git cherry-pick'所做的并不完全是“复制”提交,而是“重复”您从一个分支到正在处理的当前分支所做的工作。您也可以说git cherry pick是-“ git自动复制并粘贴您在该提交中从其他分支写入的任何内容,然后git为您将其提交到当前分支中。”因此,日期是当前日期,并且向后移动新提交 :)也没有意义。

这不是完全错误的,因为它告诉您有人提交了新代码,并且该代码是从另一个分支复制的。今天完成了。 :)