Git 如何拆除核弹起爆码,以及 topgit 0.7到0.8的变迁

Wesley13
• 阅读 475

转自:http://blog.ossxp.com/2010/01/184/

我们使用 topgit 和 git 进行公司内部版本控制已经久矣,今天要求大家彻底清除 git 配置中的 push 选项。

要求使用如下命令,先找到遗留topgit错误配置的 git 配置文件:

$ find . -maxdepth 4 -name .git -type d | \
  while read x; do \
  grep -H push $x/config; done

然后对于包含有 push 语句的 config 文件,逐一用 vi 打开,删除包含的 push 语句。

我们为什么这么做呢?这涉及到 git 的 non-fast-forward 以及 topgit 0.7含之前版本的bug 和0.8 的改进。

为什么标题这么吓人呢?什么叫做核弹起爆密码?实际上,这是我们在 Subversion 培训中经常拿来打击商业版本控制工具的一个说法,就是说 SVN 能够将错误提交的代码库中的敏感数据彻底删除(包括历史的删除),这在商业版本控制工具是很难实现的。Git作为开源版本库的No.1,当然可以支持对敏感数据的彻底删除(但是不要在删除前被别人PULL走,否则要逐一“灭口” :X-P: )。

Git的拆除核弹密码,就是如何进行 non-fast-forward的问题。

关于 Git 的FastForwards

Git 在执行 push 时,会执行一个检查:即远程分支的顶节点应该是本地将要 push 上去的新节点的子孙节点,否则报错“non-fast-forward”。

例如:

  • 远程版本库中的版本更新(可能别人已经push了新的提交),本地还是旧的提交,拒绝push。(如果提交将会删除其他人的提交)

    远程版本库:---o---o---o---o
    本地版本库:---o---o
    
  • 本地基于一个老版本做的改动,拒绝push 到服务器;

    远程版本库:---o---o---o---o
    本地版本库:---o---o
                  \--o'
    

正常情况下:

  • 第一种情况,需要执行 git pull,本地更新到最新版本,当然也就无须 push 了。

    远程版本库:---o---o---o---o
    本地版本库:---o---o
    本地执行命令: git pull 之后
    本地版本库:---o---o---o---o
    
  • 本地基于一个老版本做的改动,先要执行 git pull 并完成和服服务版本拒绝push 到服务器;

    远程版本库:---o---o---o---o
    本地版本库:---o---o
                  \--o'
    本地执行命令: git fetch; git merge; git commit 之后
    本地版本库:---o---o---o---o
                  \--o'---\o"
    然后 push 到远程服务器:git push
    远程版本库:---o---o---o---o---o"
                  \--o'-----/
    

但是如果真的要 Non-FastForwards 呢

  • 后悔了!想要撤销之前到远程版本库的 PUSH

    远程版本库:---o---o---o---o (master)
    本地版本执行:git reset --hard HEAD^^ 之后
    本地版本库:---o---o (master)
    执行强制push:git push origin +master:master (注意其中的加号)
    之后远程版本库变迁为:---o---o (master)
    
  • 同样远程的提交包含错误,需要强制用本地改动覆盖远程版本库的改动

    远程版本库:---o---o---o---o
    本地版本库:---o---o
                  \--o'
    执行命令 git push origin +master:master ,同样注意命令中的加号,强制覆盖远程版本库
    远程版本库变迁为:---o---o---o'
    

Topgit 0.7 的Bug

我们在使用 topgit 0.7 的时候,分支改动的相互覆盖,曾经让我非常烦恼。难道选择 topgit 是错误的?后来定位到问题是: topgit 在 .git/config 文件中增加了两行 push 配置:

[remote origin]
  ...
  push = +refs/top-bases/*:refs/top-bases/*
  push = +refs/heads/*:refs/heads/*

看到push配置命令中的加号了么?Topgit (0.7及更低版本)就是罪魁祸首。

参见 topgit 0.7版本的 tg-remote.sh

28 ## Configure the remote
29
30 git config --replace-all "remote.$name.fetch" "+refs/top-bases/*:refs/remotes/$name/top-bases/*" "\\+refs/top-bases/\\*:refs/remotes/$name/top-bases/\\*"
31 git config --replace-all "remote.$name.push" "+refs/top-bases/*:refs/top-bases/*" "\\+refs/top-bases/\\*:refs/top-bases/\\*"
32 git config --replace-all "remote.$name.push" "+refs/heads/*:refs/heads/*" "\\+refs/heads/\\*:refs/heads/\\*"

怎么解决这个问题呢?

当时我们想到的办法是:配置 git 服务器,让git服务器不允许 non-fast-forward 的 PUSH,配置如下:

[receive]
denyDeletes = false
denyNonFastForwards = true

Topgit 0.8 的改进

当 topgit 升级后,我们发现,令人讨厌的 non-fast-forward 的 PUSH 语句不见了,即当执行:tg remote –populate origin 时,不会在 .git/config 中再生成讨厌的 push 配置命令,而是提供一个 tg push 命令来方便分支的 push。

当然这时候我们的 git 服务器中依然配置着,不允许 non-fast-forward 的PUSH。因为毕竟还有人在使用 topgit 0.7 以下版本,或者还存在使用 topgit 0.7及以下版本创建的 git 配置。

没有Non-FastForward的日子

很多时候,自信满满的push,发现有问题,想要撤销PUSH。或者有的提交应该在分支进行,而有的人在主线master上进行,需要撤销到服务器上的PUSH。

因为服务器已经配置了不允许 non-fast-forward,因此还要麻烦管理员,手动修改服务器的配置,暂时打开允许 non-fast-forward 提交。当用户完成 non-fast-forward PUSH后,在关闭服务器设置。太太麻烦了。

管理员愤怒了

管理员愤怒了,结果很严重:

  • Topgit 必须 升级,而且要升级到 群英汇 改进后的 topgit 0.8 版本,参见
    http://github.com/ossxp-com/topgit (改进见各个分支)
  • 必须检查所有 .git/config 文件,将其中由 topgit 引入的 push 语句全部删除!
  • 服务器配置为允许 non-fast-forward 提交。

管理员又提供了一个更暴力的命令,直接将找到的 config 文件中的 push 语句删除:

$ find . -maxdepth 4 -name .git -type d | \
  while read x; do \
    grep -q push $x/config  && \
    sed -i -e '/^\s*push\s*=/ d' $x/config; \
  done
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
前端尾随者 前端尾随者
2年前
sourceTree 添加 ssh key 方法
1.使用git客户的生成公私钥:id\rsa、id\rsa.pub1.1设置Git的username和email:$gitconfigglobaluser.name"xxx"$gitconfig\globaluser.email"xxx.mail@xxx.com"1.2.生成SSH密钥过程:1.2.1.检查是不是已经存在密钥(
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这