如何删除 GitHub Gist 中的特定版本修订?

44
我在GitHub上创建了一个Gist,看到了一些我不想让任何人看到的信息。 我已经更新了文件,但每个人仍然可以访问文件的旧版本。
除了删除Gist之外,有没有办法彻底删除那个特定的版本?
我看到我不是唯一一个遇到这种问题的人(Git:删除单个远程版本),但我没有成功删除该版本。 这里提到的过程似乎可以帮助删除一些文件。我想要删除整个版本。
8个回答

37

Github有一篇关于删除敏感数据的帮助页面:

http://help.github.com/removing-sensitive-data/

由于gist只是git存储库,您应该能够在本地克隆gist,在那里进行清理,并强制推送以用清理后的存储库覆盖github版本。

是的,在考虑了一段时间后:如果<commit>是您想要“删除”的提交,请执行以下操作:

 git rebase -i <commit>^

标记<commit>所在的行为edit,保存并退出。

Git会将工作目录设置为提交<commit>后的状态。修复文件,使用git addgit commit --amend来修复提交。然后执行git rebase --continue。如果下一次提交仅删除敏感数据,则该提交可能会被自动删除,因为它在修改后没有任何更改。

然后执行git push -f以强制更新(因为现在不再是快进式更新,这意味着它会更改已发布的Git历史记录)。


谢谢你提供的链接。他们没有说明如何删除特定版本,但是你强制覆盖版本的想法很有趣。我会进行检查并更新该页面以反映我的结果。谢谢。 - Cyril N.
你是什么意思说“然后,在提交消息编辑器中删除<commit>的提交消息。”?在切换到压缩模式之后,我回到终端,然后该怎么做?(我对Git还不熟悉 :/) - Cyril N.
好的,git rebase -i 应该首先为您打开一个编辑器,列出最近的提交。最初它们都以 pick 开头。将不需要的提交的后继者的 pick 更改为 squash。保存此控制文件并退出编辑器。Squash 将把合并后的提交合并到不需要的提交中。接下来,git 应该为您打开一个编辑器,列出不需要的提交和其后继者的合并提交消息。我猜,您只想删除第一个(不需要的)提交中的所有内容。保存,退出。git 应该完成重置操作,并留下一个干净的历史记录。 - Tilman Vogel
抱歉,我的第一条回复有误,我刚刚修正了它,请再次阅读,以防万一... - Tilman Vogel
请注意,如果您的Gist只有两个提交,您可能需要执行修订操作。请参见https://dev59.com/-XRB5IYBdhLWcg3wiHhl - Peter Ehrlich
显示剩余4条评论

29

这个答案很好但有点难以理解,这里提供一个更易懂的版本。

就像Tilman Vogel所说的,gists只是存储库,因此这种方法适用于github存储库和gists。

假设只有一个包含你不想展示的密码的版本。你已经上传了新版本并删除了密码,现在想要删除之前的版本。如果有多个提交显示密码,你应该能够调整此过程。

首先,修复必须在本地机器上完成(而非在github上)。要做到这一点,请先将gist克隆到本地。如果单击私有克隆URL,gist在github上的页面应该会显示如何创建私有克隆,例如:

git clone git@gist.github.com:421xxx1.git gist-421xxx1

这将给你一个本地副本,需要rebase(即与版本进行调整)。

cd gist-421xxx1
git rebase -i eexxaa^

其中eeccaa是包含密码的(第一个)版本号。您可以在gist页面的修订栏中获取此编号。^是必需的。该命令的意思是“让我交互性地从eexxaa更改版本到最新版本”。该命令打开一个编辑器,每个版本在库中都有一行命令。默认命令是“pick”,表示“使用或保留此版本”。

编辑器中的第一行应该类似于

pick eexxaa    <- the version with the password
pick ffxxbb    <- the first version without the password

将此更改为

pick eexxaa    
squash ffxxbb 

即在没有密码的版本中将单词"pick"改为"squash"。这将要求重新设置基准以将新(无密码)版本压缩到旧(含密码)版本中,从而删除版本eexxaa。显然,您的版本将不同于eexxaa或ffxxbb,请不要在任何地方字面使用eexxaa或ffxxbb!

如@kand所述,您应该squash包含密码的每个版本。

在编辑器中保存并退出(如果是vi:x)。现在,重新设置应打开一个新的编辑器,显示两个版本的提交消息,并要求进行单个组合提交消息。对于要点,这些消息很可能为空,但您确实需要在此处放置一些内容,否则重新设置将会中止。键入消息,保存并退出,重新设置应完成。

现在,您拥有一个不包含密码版本的存储库。要将其返回到要点,请使用:

git push -f

这将强制更改上传至GitHub仓库。刷新页面后,您应该能够在浏览器中检查右侧的修订列,确认问题版本已经消失了。

就是这样!


1
不是很确定我是否做对了,但我认为你必须对每个包含密码的版本进行“压缩”更改。因此,如果在第一个没有密码的版本和第一个有密码的版本之间有多个版本,则所有这些版本都必须被压缩。 - kand
可以保留空的提交信息,请参见 https://dev59.com/vWoy5IYBdhLWcg3wcNvh#43755666 - xmedeko

5
如果您不关心在gist中显示任何修订版本,您可以执行以下操作来消除所有历史记录并仅显示一个版本。
git clone some-gist-repo
cd some-gist-repo
git rebase -i --root $tip

您可以在编辑器中查看该Gist的所有提交。只需选择第一个提交并将其余内容替换为ssquash。完成后,保存并添加提交消息,然后像这样强制推送到主分支即可。

git push -f origin master

唯一可见的修改是添加文件。

2

我尝试了一些在filter-branch中指定的方法,但都没有成功。我会将您的答案与其他答案混合在一起,尝试找到解决问题的方法。谢谢您的回答! :) - Cyril N.
我点赞了这个答案,因为在这种情况下这是正确的做法。删除存储库是没有帮助的,因为如果你想分享,你需要清理敏感信息。我建议在没有人克隆带有敏感数据的存储库时删除它。然后应用filter-branch来清理数据,然后重新提交到github。 - Eugene Sajine
另一方面,如果您想要删除一个提交,您需要使用rebase。如果您想要删除的提交距离当前HEAD有10个提交,则执行以下操作:<code>git rebase -i HEAD~16</code>通过从文件中删除提交行并保留其他提交行来编辑文件,然后保存并退出编辑器。此提交将丢失,现在您必须强制推送此分支到github上的存储库。确保您重新基于其他分支,如果它们是从您正在使用的分支派生的,则此提交将不会在历史记录中被保留/引用。 - Eugene Sajine
@Eugene,我认为squashfixup只会使得那个不愉快的“中间”状态无法访问。 - Tilman Vogel
@Tilman Vogel,这是一个非常有趣的方法,很有创意;) 不过得检查一下是否不会留下任何痕迹;) - Eugene Sajine
显示剩余3条评论

1

在2022年3月进行了测试。




许多解决方案基于squash方式。

我只是说直接删除最后一个(或多个)提交
 (不使用squash,不生成新的提交版本),这可能是常见情况。

删除提交的解决方案

在执行git rebase -i eexxaa^步骤时,
只需将最后一个不想要的提交标记为drop,然后保存。

最后执行git push -f命令
那么被删除的版本也会从gist页面中删除。

如何获取gist的仓库URL?

只需打开gist页面>复制浏览器地址栏中的URL,
 然后使用git clone $the_url即可。

注意:使用http(s)协议也需要GitHub访问令牌而非密码;
 访问令牌只需要gist权限(可以进行强制推送)。


1
在 HTTP 推送时,如果出现“存储库未找到”的情况,请将 gist 权限(唯一具有“创建 gists”权限的权限)添加到访问令牌中。 - Sam

0

补充 meesern 的回答。 当您尝试压缩或修复并重新基于继续时,需要添加注释或 --allow-empty-message。这很耗时,而且以这种方式做我的提交并没有从要点的修订列表中消失。

我找到了一个更简单的解决方案: 您可以在重新基础待办事项列表上删除不必要的提交行,:wq!git rebase --continue,和 git push -f


0

我尝试了这里的其他答案,但遇到了两个问题:

  1. 我无法变基,我认为这是因为存储库中有没有消息的提交。
  2. 我无法推送它(是的,使用force)。

我通过首先在第一个提交上创建另一个分支,并逐个cherry-picking其余的提交,而不自动提交它们(以便在提交之前可以编辑它们)来解决这两个问题。

之后,我将master分支重置为新分支:git switch master && git reset --hard temp

在推送之前,我将远程更改为SSH版本

git remote set-url origin git@github.com:<<gist id>>.git

然后,使用git push --force它推送并更改了要点修订。


0
之前的回答都不完整或对我没有用,所以我自己动手解决了。在这里分享出来,以防对其他人有用。脚本中有一些错误检查,请仔细审查并确认您的操作,因为这可能会导致数据丢失。
保存下面的脚本并执行,将您的Gist的URL作为参数传递进去。如果URL指向特定版本的路径,将使用该版本进行rebase,否则将重置您的gist到“tip”——所有先前的提交将被删除。
初始克隆后会暂停一段时间,以便您进行额外的编辑(如果需要)。

gist-clean.sh

#!/usr/bin/env bash

BASE_URL='gist.github.com'
GHUSER=$(git config --get user.name 2>/dev/null)

_usage() {
cat <<EOF

Reset a GitHub gist to clean up or remove sensitive information
usage: ${0##*/} <gist-url>

  if the URL supplied contains a revision ID (hash),
  then that revision will be used as the base.

  to get URLs to specific revisions:
    - browse to the gist on ${BASE_URL}${GHUSER:+/$GHUSER}
    - click "Revisions"
    - locate the revision you want to base from
    - click the 3 dots next to the filename -> "View file"
    - copy the URL

EOF
}

case $1 in
    -h|--help|'') _usage; exit;;
esac

[[ -n $1 ]] || { echo "supply a gist URL"; exit; }
[[ -n $GHUSER ]] || { echo 1>&2 "couldn't fetch GitHub username"; exit 1; }

if [[ $1 =~ ^https://${BASE_URL}/${GHUSER}/([a-f0-9]{32,40})/?([a-f0-9]{32,40})? ]]; then
    GIST_URL=${BASH_REMATCH[0]}
    GIST_ID=${BASH_REMATCH[1]}
    REV_HASH=${BASH_REMATCH[2]}
    CLONE_URL="https://${BASE_URL}/${GIST_ID}.git"
    TEMP_DIR="/tmp/gist${GIST_ID}"
    rm -rf "${TEMP_DIR}" 2>/dev/null
    mkdir -p "${TEMP_DIR}"
    if ! git clone "${CLONE_URL}" "${TEMP_DIR}" ; then
        exit 1
    fi
    cd "${TEMP_DIR}" || exit 1
    if [[ -n ${REV_HASH} ]]; then
        git reset --hard "${REV_HASH}"
    fi
    BRANCH=$(git symbolic-ref --short HEAD)
    cat <<-EOF
    ┌──────────────────────────────────────┐
    │                                      │
    │ PAUSED - YOU CAN NOW EDIT THE FILES  │
    │                                      │
    │           !!! WARNING !!!            │
    │                                      │
    │ ALL CONTENTS OF THE REMOTE GIST WILL │
    │  BE REPLACED BY THE LOCAL COPY, AND  │
    │     ALL REVISIONS WILL BE LOST!      │
    │                                      │
    └──────────────────────────────────────┘
    EOF
    read -r -p 'press <ENTER> to continue or ⌃c to ABORT '
    rm -rf .git
    git init
    git add .
    git commit -m 'initial commit'
    git remote add origin "git@github.com:${GIST_ID}.git"
    git push --set-upstream origin "$BRANCH" --force
    cd ..
    rm -rf "${TEMP_DIR}"
    open "${GIST_URL}"
else
    echo 1>&2 "does not appear to be a valid gist URL"
    exit 1
fi

例子:

./gist-clean.sh https://gist.github.com/your-git-username/f184a9c638b75525a65b3e1a7298e6d7/30e87b313bdba9a4bd92746418217ddda958b8cd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接