除了删除Gist之外,有没有办法彻底删除那个特定的版本?
我看到我不是唯一一个遇到这种问题的人(Git:删除单个远程版本),但我没有成功删除该版本。 这里提到的过程似乎可以帮助删除一些文件。我想要删除整个版本。
Github有一篇关于删除敏感数据的帮助页面:
http://help.github.com/removing-sensitive-data/
由于gist只是git存储库,您应该能够在本地克隆gist,在那里进行清理,并强制推送以用清理后的存储库覆盖github版本。
是的,在考虑了一段时间后:如果<commit>
是您想要“删除”的提交,请执行以下操作:
git rebase -i <commit>^
标记<commit>
所在的行为edit
,保存并退出。
Git会将工作目录设置为提交<commit>
后的状态。修复文件,使用git add
和git commit --amend
来修复提交。然后执行git rebase --continue
。如果下一次提交仅删除敏感数据,则该提交可能会被自动删除,因为它在修改后没有任何更改。
然后执行git push -f
以强制更新(因为现在不再是快进式更新,这意味着它会更改已发布的Git历史记录)。
这个答案很好但有点难以理解,这里提供一个更易懂的版本。
就像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仓库。刷新页面后,您应该能够在浏览器中检查右侧的修订列,确认问题版本已经消失了。
就是这样!
git clone some-gist-repo
cd some-gist-repo
git rebase -i --root $tip
您可以在编辑器中查看该Gist的所有提交。只需选择第一个提交并将其余内容替换为s
或squash
。完成后,保存并添加提交消息,然后像这样强制推送到主分支即可。
git push -f origin master
squash
或fixup
只会使得那个不愉快的“中间”状态无法访问。 - Tilman Vogel在2022年3月进行了测试。
许多解决方案基于squash
方式。
我只是说直接删除最后一个(或多个)提交
(不使用squash,不生成新的提交版本),这可能是常见情况。
在执行git rebase -i eexxaa^
步骤时,
只需将最后一个不想要的提交标记为drop
,然后保存。
最后执行git push -f
命令
那么被删除的版本也会从gist页面中删除。
只需打开gist页面>复制浏览器地址栏中的URL,
然后使用git clone $the_url
即可。
注意:使用http(s)协议也需要GitHub访问令牌而非密码;
访问令牌只需要gist
权限(可以进行强制推送)。
补充 meesern 的回答。
当您尝试压缩或修复并重新基于继续时,需要添加注释或 --allow-empty-message
。这很耗时,而且以这种方式做我的提交并没有从要点的修订列表中消失。
我找到了一个更简单的解决方案:
您可以在重新基础待办事项列表上删除不必要的提交行,:wq!
,git rebase --continue
,和 git push -f
。
我尝试了这里的其他答案,但遇到了两个问题:
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
它推送并更改了要点修订。
#!/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
git rebase -i
应该首先为您打开一个编辑器,列出最近的提交。最初它们都以pick
开头。将不需要的提交的后继者的pick
更改为squash
。保存此控制文件并退出编辑器。Squash 将把合并后的提交合并到不需要的提交中。接下来,git 应该为您打开一个编辑器,列出不需要的提交和其后继者的合并提交消息。我猜,您只想删除第一个(不需要的)提交中的所有内容。保存,退出。git 应该完成重置操作,并留下一个干净的历史记录。 - Tilman Vogel