如何查看分支上任何给定 git 提交的代码状态?

How to view status of code at any given git commit on a branch?

我有一个 master 分支,其中有几个月与 Web 项目相关的提交。

我有时需要通过浏览器查看网站在过去特定时间点的样子。

我目前checkout master分支,select时间点并创建了一个分支。然后我可以在那个时间点在浏览器中看到该站点。

我应该这样做还是有更简单的方法?

运行 git status 将为您提供分支的当前状态。暂存文件、未暂存修改文件、是否处于变基/合并等

为了在开发过程中持续查看站点,我建议使用本地服务器在本地为您提供站点服务,您可以在其中不断地 refresh 浏览器查看更改。

一种流行的方式(也用于 Github 页面)是通过 Jekyll 为网站提供服务。

您的方法是其中一种方法。 有几种方法可以更快地到达那里(一点点)。

  1. 如果您有某种网络 UI 可以查看存储库和相关提交(例如,如果您的存储库托管在 GitHub 或 BitBucket 上),您可以找出提交的 SHA1 散列并按散列执行结帐。命令将是:

    git checkout <sha1>
    

  1. 如果您对相对于某个时间点的状态感兴趣,您可以使用一个简单的命令首先找到 "closest" 提交哈希,然后检查它。例如,如果您需要查看代码在 2017 年 3 月 1 日的状态,您实际上对发生在 03/01/2017 00:00 之前的最新提交感兴趣。命令将是:

    git checkout `git rev-list -n 1 --before="2017-03-01 00:00" master
    

    值得一提的是,如果您 运行 正在使用 Windows,则需要使用略有不同的语法。这是相同代码的 PowerShell 版本:

    $sha = git rev-list -1 --before="2017-03-01 00:00" master
    git checkout $sha
    

  1. 最后,如果您知道某个提交代表了这些时间点之一,您以后会need/want回来,您可以使用Git稍后标记功能和结帐标签。例如,要标记提交,您可以 运行(将 sha1 替换为提交哈希 ):

    git tag -a some-point-in-time <sha1>
    

    当你想"come back"到这个时间点你可以运行:

    git checkout -b master some-point-in-time
    

您可以在特定的早期提交处检出 master 分支,例如

git checkout <SHA-1 of some commit in master>

这将使您进入分离的 HEAD 状态。从这里,您可以实际构建您的项目、部署并查看它的外观。

如果您想从较早的提交创建一个真正的分支,您可以通过以下方式进行:

git checkout -b new_branch_from_old_commit

您很可能不需要创建新分支。环顾四周后,您可以 return 到您当前的 master 分支,只需检查一下即可:

git checkout master

您可以简单地 git checkout 通过哈希 ID 进行提交,尽管这听起来很可怕 "detached HEAD".

背景

分支和标签是命名某些特定提交的方式。就此而言,HEAD 只是一种命名分支的方式,或者有时是一个特定的提交。

因此:

git log

显示您从 HEAD 开始提交,并且:

git log master

显示您从 master 开始提交。如果HEAD个名字master,这两个做的事情完全一样。

添加--oneline,或者我偏爱"DOG"—--decorate --oneline --graph;还要考虑 "A DOG"、--all --decorate...——稍微压缩输出:

* e0688e9 (HEAD -> master, origin/master, origin/HEAD) git svn: fix ...
* 3bc5322 First batch after 2.12
* 3e5c639 Merge branch 'rl/remote-allow-missing-branch-name-merge'

在这里我们看到 HEAD 名称 master,还有两个提交名称 e0688e9

每个提交都会命名一个先前的提交(它的父提交)。这是如何 git log 能够显示多个提交。我们说分支和标签名称 指向 e0688e9 这样的提交,并且那个提交指向它的前身 3bc5322,它又指向另一个,等等。

如果我们将这些绘制为一系列单字母名称提交(比 3bc5322... 哈希 ID 更实用),我们会得到如下所示的内容:

A <- B <- C   <-- master

此处名称 master 指向 CC 指向 BB 指向 AA 是有史以来第一次提交,所以它 不能 指向任何更远的地方,也不会。这就是 git log 知道 停止的方式!

分离头

通常,HEAD 包含实际的分支名称。在上面的 git log 输出中,我们看到 HEAD 名为 master。正在做:

git checkout branch

告诉 Git 不仅要检查 branch 命名的特定提交,还要将 name branch 放入 HEAD。我们说 HEAD attached 到分支。但是我们可以通过将原始哈希 ID 放入 HEAD 分离 它,我们通过 运行:

git checkout 3bc5322

这与在那里有一个分支名称的作用相同,除了 ...

新提交移动分支

当您进行 提交时,Git 将新提交写回当前提交,然后更改 当前分支 以便它指向新的提交。例如,如果我们添加一个新的提交 D 到我们的三提交 A-B-C 设置中,提交本身看起来像这样:

A <- B <- C <- D

但是 D 的名字是那些丑陋的大哈希 ID 之一,我们无法记住它。相反,我们让 Git 帮我们记住它——将它写入当前分支的名称。如果当前分支是 master,这将更改 master,使其不再指向 C:

A <- B <- C <- D   <-- master

现在master为我们记住了D,树枝本身也长大了!

但是,问题来了:Git 知道要更新哪个分支的方式是它存储在 HEAD 中。如果您有一个分离的 HEAD,则没有当前分支 name。在这种情况下,Git 将新提交 记住为 HEAD。假设我们添加 D,同时我们通过哈希 ID 签出 B

A--B--C     <-- master
    \
     D      <-- HEAD

如果我们 git checkout master,那会用名称 master 覆盖 HEAD,"forgetting" 我们的新提交。

这并不是真的危险,除非它可能是:也许你写了一些非常棒的代码,你会 never be able to write again,但现在你已经失去了它,哦不!因此,为此目的,您可以在任何提交时 创建一个新的分支名称 包括 一个分离的 HEAD,使用 git checkout -b:

git checkout -b newbranch

现在我们有:

A--B--C     <-- master
    \
     D      <-- newbranch (HEAD)

或者,当然,您可以给提交 B 一个标签,然后检查它,然后创建新的提交 D。这里的要点是 commits 才是真正重要的;这些名称只是给我们 找到它们的方法

命名提交的方式有很多种

您可以使用分支和标签名称,但您可以添加后缀和计数:

HEAD~1

例如表示"start at HEAD, but then walk back once to HEAD's parent"。 (如果提交是 merge commit——一个有多个父项——~ 后缀选择 first 父项,每次.) 或者,您可以将 @{...}HEAD 或分支名称一起使用:

master@{1.week.ago}

它使用 Git 调用 masterreflog 来查看哪个提交 master 恰好在一周前命名(如果那是某天你多次更改它,Git 刚好在 7*24*60*60 秒前;Git 在这里非常字面意思)。

还有很多其他方法可以找到提交,包括在提交 messages 中搜索文本。研究 the gitrevisions documentation 以获取更多命名提交的方法。