从远程删除敏感分支但保留本地提交的文件
Remove sensitive branch from remote but keep files committed locally
我的本地 git 存储库有 2 个远程:private
和 public
。错误地,我已经 运行 git push public feature_branch
,所以现在 feature_branch
上的代码变成了 public,即使它应该保持隐藏(现在)。
这不是一个大的隐私问题,但我仍然想解决它。
我已经 deleted the branch using the GitHub GUI。我还需要做其他事情吗?
我不希望任何人在分支 public 仅可见的 30 秒内设法克隆存储库 - 我只关心缓存或其他 git clone
现在可以下载的新东西。
运行 git push public --delete feature_branch
现在给出 error: unable to delete 'feature_branch': remote ref does not exist
,所以看起来是正确的。
我知道 git filter-branch
,但我读到它处理的是一开始就不应该提交的数据 - 我确实想提交代码,只是没有它 public在我决定稍后使用之前可用。
在这种情况下,您已经完成了所有需要做的事情。
(如果你愿意,可以在这里停下来。)
Long-ish: 这个怎么想
Git 实际上就是 提交 。 Git 存储库可以被认为是一个大的提交数据库——或者实际上,Git objects,但是提交是那些在你使用的级别——你,或者至少 Git,将通过它们的键检索这些 objects,这些键是它们的哈希 ID。
Git 存储库的更准确描述是 两个 数据库:Git objects 中的一个大数据库,包括提交,以及 names 中的一个小(或至少,通常小得多)。这些名称包括所有分支和标记名称。
名称存在的原因有两个:
哈希 ID 又大又丑,没有人能记住它们。每个名字为我们记住一个哈希ID。
提交,特别是形成链。 Git 查找 old 提交的方法是查找 latest 提交——其哈希 ID 存储在分支名称中——并向后工作.
承诺 不能 以这种方式找到——不能通过从名字开始到达,如果有必要,向后工作——被删除。也许不是马上,但对大多数人来说已经足够快了。 (您遇到的安全问题——意外提交然后推送敏感数据——是 "soon enough" 不存在的地方,或者至少,不能假设。)
因此这些名称让我们 找到 提交。如果他们没有名字,我们就找不到他们,他们也可能不存在(很快就会不存在)。名称不必直接找到它们,只能间接找到它们。但是一旦做出承诺,它就永远不会改变。因此,从 child 提交到他们的 parents,始终只提交 backwards。新提交不会影响现有提交。 Git 只能工作 backwards,从 name 到 commit 到 parent 再到 grandparent,等等
克隆存储库的行为包括(在中间)做这两件事,虽然不是按这个顺序——它们在内部有点混乱:
首先,他们拥有了他们的名字数据库。 我们的 Git 通常采用这组名称, 丢弃 其中大部分:
我们保留 none、部分或全部 tag 名称,在各种不值得在此描述的条件下。
我们保留他们的 分支 名称,但将它们重命名为我们的 remote-tracking 名称(例如, origin/master
而不是 master
).
如果我们想保持所有名称不变,我们可以使用git clone --mirror
(这有很多我们将在这里跳过的后果).我们通常不这样做,因为它对正常工作没有用。
最后,原始存储库移交所有提交——或者无论如何可以通过我们复制的名称找到的所有提交。
结果是一个新的存储库:一对新的数据库。1
我上面说在中间,因为git clone
其实有六个步骤:
- 创建一个新的空目录(或使用现有的空目录);
- 在此目录中创建存储库,并在那里完成其余工作;
- 添加一个名为
origin
的 remote 或其他选定的名称,以保存 URL;
- 执行所需的任何其他配置;
- 运行
git fetch
,数据库复制;
- 运行
git checkout
.
这是最后一步——git checkout
——在新克隆中创建一个 分支 名称。此步骤中签出的分支是 origin
Git 推荐的分支,通常是 master
,或者您在 git clone
命令行上选择的其他名称。2
当您使用 GitHub GUI 在 GitHub 的 Git 中删除 分支名称 时,这:
- 从姓名数据库中删除了 姓名;
- 因此,使一些提交无法访问,这样它们就不会被看到,因此不会被复制。
因此,您创建的任何克隆都没有 remote-tracking 名称(重命名的分支名称),也没有提交(它们在复制过程中未找到并且未被转移)。3
1存储库还包括比这两个数据库更多的内容。例如,每个名字——每个 ref 或 reference,用 Git 的术语来说——可以有自己的 mini-database以前存储的哈希 ID。这些是 reflogs,它们实际上只是 .git/logs/
中的纯文本文件。但是这些不会被复制d.只复制了两个主数据库,没有复制一个名称as-is:它是由获取步骤重建的。
通常,当您在存储库中处理提交时,您 Git 将一个特定提交的快照提取到您的 work-tree 中。 work-tree 是,在相当强烈的意义上,不是存储库本身的一部分: repository 是 .git
目录中的内容。 so-called bare 克隆缺少 work-tree,但仍然是一个存储库;大多数 server-side Git 都是裸克隆,例如 GitHub 上的那些。
2如果愿意,您可以在此处选择一个 tag 名称,在这种情况下,git checkout
会导致detached HEAD and no branch names in the new clone.
3Git 从来没有做出过特别强烈的 安全 承诺,所以可能有一些方法可以欺骗对方 Git——在 origin
——允许复制提交。但是您要防止意外访问,而不是故意访问。
我的本地 git 存储库有 2 个远程:private
和 public
。错误地,我已经 运行 git push public feature_branch
,所以现在 feature_branch
上的代码变成了 public,即使它应该保持隐藏(现在)。
这不是一个大的隐私问题,但我仍然想解决它。
我已经 deleted the branch using the GitHub GUI。我还需要做其他事情吗?
我不希望任何人在分支 public 仅可见的 30 秒内设法克隆存储库 - 我只关心缓存或其他 git clone
现在可以下载的新东西。
运行 git push public --delete feature_branch
现在给出 error: unable to delete 'feature_branch': remote ref does not exist
,所以看起来是正确的。
我知道 git filter-branch
,但我读到它处理的是一开始就不应该提交的数据 - 我确实想提交代码,只是没有它 public在我决定稍后使用之前可用。
在这种情况下,您已经完成了所有需要做的事情。
(如果你愿意,可以在这里停下来。)
Long-ish: 这个怎么想
Git 实际上就是 提交 。 Git 存储库可以被认为是一个大的提交数据库——或者实际上,Git objects,但是提交是那些在你使用的级别——你,或者至少 Git,将通过它们的键检索这些 objects,这些键是它们的哈希 ID。
Git 存储库的更准确描述是 两个 数据库:Git objects 中的一个大数据库,包括提交,以及 names 中的一个小(或至少,通常小得多)。这些名称包括所有分支和标记名称。
名称存在的原因有两个:
哈希 ID 又大又丑,没有人能记住它们。每个名字为我们记住一个哈希ID。
提交,特别是形成链。 Git 查找 old 提交的方法是查找 latest 提交——其哈希 ID 存储在分支名称中——并向后工作.
承诺 不能 以这种方式找到——不能通过从名字开始到达,如果有必要,向后工作——被删除。也许不是马上,但对大多数人来说已经足够快了。 (您遇到的安全问题——意外提交然后推送敏感数据——是 "soon enough" 不存在的地方,或者至少,不能假设。)
因此这些名称让我们 找到 提交。如果他们没有名字,我们就找不到他们,他们也可能不存在(很快就会不存在)。名称不必直接找到它们,只能间接找到它们。但是一旦做出承诺,它就永远不会改变。因此,从 child 提交到他们的 parents,始终只提交 backwards。新提交不会影响现有提交。 Git 只能工作 backwards,从 name 到 commit 到 parent 再到 grandparent,等等
克隆存储库的行为包括(在中间)做这两件事,虽然不是按这个顺序——它们在内部有点混乱:
首先,他们拥有了他们的名字数据库。 我们的 Git 通常采用这组名称, 丢弃 其中大部分:
我们保留 none、部分或全部 tag 名称,在各种不值得在此描述的条件下。
我们保留他们的 分支 名称,但将它们重命名为我们的 remote-tracking 名称(例如,
origin/master
而不是master
).如果我们想保持所有名称不变,我们可以使用
git clone --mirror
(这有很多我们将在这里跳过的后果).我们通常不这样做,因为它对正常工作没有用。
最后,原始存储库移交所有提交——或者无论如何可以通过我们复制的名称找到的所有提交。
结果是一个新的存储库:一对新的数据库。1
我上面说在中间,因为git clone
其实有六个步骤:
- 创建一个新的空目录(或使用现有的空目录);
- 在此目录中创建存储库,并在那里完成其余工作;
- 添加一个名为
origin
的 remote 或其他选定的名称,以保存 URL; - 执行所需的任何其他配置;
- 运行
git fetch
,数据库复制; - 运行
git checkout
.
这是最后一步——git checkout
——在新克隆中创建一个 分支 名称。此步骤中签出的分支是 origin
Git 推荐的分支,通常是 master
,或者您在 git clone
命令行上选择的其他名称。2
当您使用 GitHub GUI 在 GitHub 的 Git 中删除 分支名称 时,这:
- 从姓名数据库中删除了 姓名;
- 因此,使一些提交无法访问,这样它们就不会被看到,因此不会被复制。
因此,您创建的任何克隆都没有 remote-tracking 名称(重命名的分支名称),也没有提交(它们在复制过程中未找到并且未被转移)。3
1存储库还包括比这两个数据库更多的内容。例如,每个名字——每个 ref 或 reference,用 Git 的术语来说——可以有自己的 mini-database以前存储的哈希 ID。这些是 reflogs,它们实际上只是 .git/logs/
中的纯文本文件。但是这些不会被复制d.只复制了两个主数据库,没有复制一个名称as-is:它是由获取步骤重建的。
通常,当您在存储库中处理提交时,您 Git 将一个特定提交的快照提取到您的 work-tree 中。 work-tree 是,在相当强烈的意义上,不是存储库本身的一部分: repository 是 .git
目录中的内容。 so-called bare 克隆缺少 work-tree,但仍然是一个存储库;大多数 server-side Git 都是裸克隆,例如 GitHub 上的那些。
2如果愿意,您可以在此处选择一个 tag 名称,在这种情况下,git checkout
会导致detached HEAD and no branch names in the new clone.
3Git 从来没有做出过特别强烈的 安全 承诺,所以可能有一些方法可以欺骗对方 Git——在 origin
——允许复制提交。但是您要防止意外访问,而不是故意访问。