Published on

Github is Leaking Your Commit Timezone

Authors
  • avatar
    Name
    ttyS3
    Twitter

之前有一用一个 Chrome 插件优化 Github UI 体验的,叫 refined-github

当然现在我已经没有使用了,主要是由于 Github UI 更新太快,有时候它追不太上。容易导致一些奇怪的 UI问题。

它有一个神奇的功能是, 你访问他人的 github profile, 或者, 鼠标悬浮在某人头像上时,它会显示出这个用户是在哪个时区,此时此刻他是几点。

后面我发现,它其实是通过 github restful api 去获取仓库的 commit log 信息, 然后找到最近的一条是作者本人提交的 commit, 通过 git 本身记录的原 commit log 里的时区,就能知道作者的真正所在时区了。

时区信息是如何获取到的?

但是你如果直接通过 github ui 去访问一个commit , github 总是给你转换成了你当地的时区显示的,因此看不出来。 比如 https://github.com/refined-github/refined-github/commit/d3e49584cd0f943d7ad1102290ae682f53ee4e97

比如通过这个 api: https://docs.github.com/en/rest/commits/commits?apiVersion=2022-11-28 是不行的。

通过这个 api 你拿到的还是github转换后的 UTC 时区的时间。

怎么样拿到本地时区呢?

我们看下这个插件是怎么做的。

它先访问用户的 events, 比如:

curl 'https://api.github.com/users/DerTimonius/events' \
  -H 'authority: api.github.com' \
  -H 'accept: application/vnd.github.v3+json' \
  -H 'accept-language: en-US' \
  -H 'cache-control: no-cache' \
  -H 'dnt: 1' \
  -H 'origin: https://github.com' \
  -H 'pragma: no-cache' \
  -H 'referer: https://github.com/refined-github/refined-github/commits/main' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'

然后就能拿到最近的一些公开的提交事件, 里面会有 commit url:

{
      "repository_id": 719513204,
      "push_id": 15847598750,
      "size": 1,
      "distinct_size": 1,
      "ref": "refs/heads/main",
      "head": "a27d4e5d855d446e942ce40d03082c2e9ba9964e",
      "before": "69eebb7556084c6e2f33d67b3bea599c80ffac08",
      "commits": [
        {
          "sha": "a27d4e5d855d446e942ce40d03082c2e9ba9964e",
          "author": {
            "email": "[email protected]",
            "name": "Timon Jurschitsch"
          },
          "message": "up to chapter 10",
          "distinct": true,
          "url": "https://api.github.com/repos/DerTimonius/next-14-learn/commits/a27d4e5d855d446e942ce40d03082c2e9ba9964e"
        }
      ]
    }

比如这里我们拿到了 https://api.github.com/repos/DerTimonius/next-14-learn/commits/a27d4e5d855d446e942ce40d03082c2e9ba9964e

然后再请求 commit 详情接口:

curl 'https://api.github.com/repos/DerTimonius/next-14-learn/commits/a27d4e5d855d446e942ce40d03082c2e9ba9964e' \
  -H 'authority: api.github.com' \
  -H 'accept: application/vnd.github.v3+json' \
  -H 'accept-language: en-US' \
  -H 'cache-control: no-cache' \
  -H 'dnt: 1' \
  -H 'origin: https://github.com' \
  -H 'pragma: no-cache' \
  -H 'referer: https://github.com/refined-github/refined-github/commits/main' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'

然后这里其实还是格式化成了 UTC 时区。嗯, Github 还是比较讲究的。

但是接下来, 这个插件又请求了:

curl 'https://api.github.com/repos/DerTimonius/next-14-learn/commits/a27d4e5d855d446e942ce40d03082c2e9ba9964e' \
  -H 'authority: api.github.com' \
  -H 'accept: application/vnd.github.v3.patch' \
  -H 'accept-language: en-US' \
  -H 'cache-control: no-cache' \
  -H 'dnt: 1' \
  -H 'origin: https://github.com' \
  -H 'pragma: no-cache' \
  -H 'referer: https://github.com/refined-github/refined-github/commits/main' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0' 

没错,请求的 url 一样,但是 accept 头变成了 application/vnd.github.v3.patch

嗯,这应该是拿到原始时区的唯一方式了。

From a27d4e5d855d446e942ce40d03082c2e9ba9964e Mon Sep 17 00:00:00 2001
From: Timon Jurschitsch <[email protected]>
Date: Thu, 16 Nov 2023 12:29:39 +0100
Subject: [PATCH] up to chapter 10

---
 app/dashboard/(overview)/loading.tsx |  5 +++++
 app/dashboard/(overview)/page.tsx    | 33 ++++++++++++++++++++++++++++
 app/dashboard/page.tsx               |  3 ---
 app/lib/data.ts                      | 25 +++++++++++++++++----
 app/ui/dashboard/cards.tsx           | 15 +++++++++----
 app/ui/dashboard/latest-invoices.tsx | 18 +++++++--------
 app/ui/dashboard/revenue-chart.tsx   | 24 ++++++++++----------
 app/ui/invoices/table.tsx            | 10 +++++----
 package.json                         |  7 ++++--
 pnpm-lock.yaml                       |  2 +-
 10 files changed, 102 insertions(+), 40 deletions(-)
 create mode 100644 app/dashboard/(overview)/loading.tsx
 create mode 100644 app/dashboard/(overview)/page.tsx
 delete mode 100644 app/dashboard/page.tsx

然后我们看 Date: Thu, 16 Nov 2023 12:29:39 +0100 这里,原始的时区就出来了。

插件相关代码: https://github.com/refined-github/refined-github/blob/d3e49584cd0f943d7ad1102290ae682f53ee4e97/source/features/user-local-time.tsx#L20

如何避免时区泄露?

已经存在的仓库,当然没得救了。后面的提交至少可以挽回一下吧。

方法就是使用 git alias, 原来你用 git commit 提交, 现在只需要换成 git ci 即可(为什么喜欢叫 ci? 从 svn 时代就习惯了吧)

[alias]
	#ci = commit
	ci = "!f() { git commit --date=\"$(date --utc +%Y-%m-%dT%H:%M:%S%z)\" \"${@}\"; }; f"
	#cc = cz commit
	cc = "!f() { git cz commit -- --date=\"$(date --utc +%Y-%m-%dT%H:%M:%S%z)\" \"${@}\"; }; f"