simonid
12/2/2017 - 3:46 PM

git使用随笔

git使用随笔

解决远程仓库开启双步验证无法push的bug

问题描述:
本人在同个目录下加了2个远程仓库(bitbucket和gitlab,bitbucket是主要的,gitlab是附加的)。但是push的时候会弹出gitlab的验证框,输入用户名和密码拒绝访问

解决:
用户需要在gitlab设置中找到token选项,选择合适的权限,然后push之后再有弹出验证框的话就将token粘贴进去(据闻动态验证器生成的验证码也是可以的,没有测试)

git本地绑定多个远程仓库

需求分析:
本地有一个文件夹,里面的文件需要同时上传到github、gitlab、bitbucket等仓库

首先,需要解决用户的ssh问题
生成ssh的流程一般是通过ssh-keygen -t rsa -C "yourmail@gmail.com",然后一路回车就实现了。
假如是要登录多个远程仓库,可以将目录下的唯一一个id_rsa.pub复制到不同的平台,但是这样有一定的安全隐患(额,如果是菜鸡就杞人忧天了,没人搭理你的仓库)。

所以用户需要在自己的ssh目录下生成多个密钥对,方法和前面一样,只是注意要自定义文件名

接着配置文件,在.ssh目录下新建config

Host github.com
    User email1
    Hostname ssh.github.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa


Host gitlab.com
    User email2
    Hostname gitlab.com
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa-gitlab


Host bitbucket.org
    User email3
    Hostname bitbucket.org
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa-bitbucket

添加公钥到远程仓库设置后,
然后分别用类似ssh -T git@bitbucket.org的命令测试连接

在同一个目录下新增多个远程地址

git remote set-url --add origin <url>

#url就是不同平台的工程仓库地址

检查:

git remote -v

显示当前所有远程库的详细信息,显示格式为 远程库名字 url连接(类型)

这样,以后it push origin master就会把该目录下的文件推送到多个不同仓库了

注意

使用git push origin master时,你可以push到origin的多个url地址,
但是使用 git pull时,只能拉取origin里的一个url地址(即fetch-url),这个fetch-url默认为 你添加的到origin的第一个地址,
如果你想更改,只需要更改config文件里,那三个url的顺序即可,fetch-url会直接对应排行第一的那个utl连接。

参考:
git给本地添加多个url地址

git各种回滚方式

首先明确git的工作区:

  • 工作目录:本地文件夹,git仓库位于工作目录下,工作目录下有加入git仓库(tracked)和未加入(untracked)之分
  • 本地仓库:包括 1.index文件(暂存区),用来临时保存改动 2.master分支 3.指向该分支的指针HEAD,并且它总是指向当前版本

情况1:取消暂存的文件

git reset HEAD <filename>

文件通过git add加入到了暂存区,但是尚未提交,可以用该命令将git add新增到暂存区的修改撤销

情况2:撤销对文件的修改

git checkout -- <filename>

假如从GitHub上clone了一个项目,并且对内容做了修改,修改后不想保存,想回退到最原始或者上次提交的样子可以使用这个命令

情况3:回滚版本

git reset --hard HEAD^/<commit id>

假如文件从暂存区提交了信息(commit)到本地版本库,但是还没有提交到远程仓库,可以用这个命令回滚。这里的commit id至少就是上上次的提交id
要注意这里的commit id并不是commit的信息

  • HEAD:HEAD代表当前版本,上一次版本是HEAD^,上上次版本是HEAD^^,以此类推,往前推10个版本,那么就是HEAD~10
  • commit id:版本号,是一串哈希值,可以通过git reflog查看

demo:

git reset --hard HEAD^  #退到上一个版本
git reset --hard a324fe2  #退到某个版本

来源:
初尝Git · 强效后悔药

长期更新

### Git没有办法merge某个branch中的指定的文件,只能将整个branch进来
```
$ git merge <branch-name> -m "commit...."
```

### Github删除远程服务器文件并保留本地文件
#### 删除单个文件
```
git rm --cached xxx
git commit -m "delete xxx"
git push origin master
```
#### 删除目录
```
git rm --cached -r xxx
git commit -m "delete xxx"
git push origin master
```

一些零散的git-

Git没有办法merge某个branch中的指定的文件,只能将整个branch进来

$ git merge <branch-name> -m "commit...."

Github删除远程服务器文件并保留本地文件

删除单个文件

git rm --cached xxx
git commit -m "delete xxx"
git push origin master

删除目录

git rm --cached -r xxx
git commit -m "delete xxx"
git push origin master

git push失效

git push一直卡住没进展

错误如下:

fatal: unable to access 'https://github.com/simonid/Note.git/': Failed to connect to github.com port 443: Timed out

超时错误,怀疑是网络原因,于是参考教程:
[git 设置和取消代理](https://gist.github.com/laispace/666dd7b27e9116faece6)

设置好代理之后,又出现下面问题:

fatal: unable to access 'https://github.com/simonid/Note.git/': OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443

看来这应该不是网络问题了,而是ssh密钥出错(本人有用git bash来链接远程主机的习惯)

那么重新设定一个ssh吧,参考:
git生成ssh key及本地解决多个ssh key的问题

生成新密钥对:

ssh-keygen -t rsa -f ~/.ssh/id_rsa.github -C "xxx@gmail.com"

然而,结果ssh -T git@github.com测试出现:

ssh: connect to host github.com port 22: Connection timed out

然后参照一些网上的教程:
http://www.anool.net/2016/08/16/git-problem/
.ssh目录下新建一个文件,文件内容:

Host github.com
User xxx@163.com (你注册github时的邮箱,这里使用注册的用户名也行)
Hostname ssh.github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
Port 443

会弹出下列类似的说明,有一部分警告:

The authenticity of host ‘[ssh.github.com]:443 ([207.97.227.248]:443)’ can’t be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? y
Please type ‘yes’ or ‘no’: yes
Warning: Permanently added ‘[ssh.github.com]:443,[207.97.227.248]:443’ (RSA) to the list of known hosts.

假如使用:

ssh -T -p 443 git@ssh.github.com

那么就不会有上述的警告了

虽然这样连接成功了,但是在push的时候依旧是超时,一不做二不休,干脆把.ssh目录下的密钥和配置全删除了,再新建一个。
参考了一下StackOverflow上的帖子
ssh: connect to host github.com port 22: Connection timed out

所以下面才是终极大招

在项目的目录下,输入

git config --local -e

url = https://github.com/username/repo.git

改为

url = git@github.com:username/repo.git

这里正好和原帖相反,然后再push,成功

git lfs实践

git-lfs-wiki

Use Git LFS with Bitbucket

git lfs是专门用来解决大文件上传的工具,它的实现原理:
将需要添加到LFS的文件额外添加到LFS专属仓库中,仓库只保留这些大文件的文本链接,当从远程仓库拉取文件时,LFS的钩子将自动将这些文本链接恢复为LFS的实际内容,如图所示:


最大的优势

使用LFS管理仓库,用户在clone的时候可以更快,并且也不能察觉出用了lfs

几点疑惑:

1.LFS支持多大的文件存储?
github目前支持1G,bitbucket和gitlab暂时不知道

2.1G的存储空间不大,那么应该也存不到多少东西吧?
凡是上传到LFS的文件都会进行压缩,网上有人上传1G大小的文件,经过LFS压缩只有几m

3.既然压缩了大小,那么本地的文件是不是也压缩?上传速度会加快吗?
不会,和普通push一样

安装使用

首先下载LFS的安装包,点击安装后,执行

git lfs install

该步骤执行一次就够了,此后上传文件和普通的操作类似,只是多了lfs命令
LFS还会创建post-checkoutpost-commitpost-mergepre-push几个全局钩子。当我们在一个使用 LFS 的仓库执行类似checkoutcommitmergepush 的 Git 操作

改造仓库

我们需要另外对大文件进行分类管理,将其传到LFS仓库

git lfs track "*.pdf"

#将路径下的所有pdf传送到LFS

执行完上述命令后会在仓库中创建一个.gitattribute文件,里面记录的内容就是track的信息

git的钩子就是通过该文件确定当前仓库是否通过LFS管理,所以不要忘了将它添加

git add .gitattribute

然后就可以像正常操作那样提交了

git add *.pdf
git commit -m "add pdf"
git push origin master

注意

这个改造过程只会把当前这次 commit 的指定类型文件改成用 LFS 才存储,而不会影响所有历史记录。对于我们的 SDK 仓库,仓库本身已经非常庞大,直接这么改造是没有任何瘦身效果的。所以最好的做法就是重新创建一个仓库,把各个分支最新的快照同步过来。

针对上传文件过大可能会导致中途停止的问题

很多时候是因为buffer不够大造成的
出现下面类似问题:

Delta compression using up to 4 threads.
Compressing objects: 100% (8210/8210), done.
Writing objects: 100% (11506/11506), 21.75 MiB | 0 bytes/s, done.
Total 11506 (delta 2213), reused 11504 (delta 2211)
efrror: RPC failed; result=56, HTTP code = 200
atal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly
Everything up-to-date

解决:

git config http.postBuffer 524288000

#这里将buffer设置为500M,可以自定义

更多参考:化繁为简的企业级 Git 管理实战(五):二进制大文件的版本控制