Git版本控制

Git命令

1. 注册Github账号,让Git 知道这台电脑做的修改要连结到哪一个使用者

1
2
git config --global user.name "<Your Name>"
git config --global user.email "< your@gmail.com >"

2. 建立本机repo,初始化git管理

1
2
3
4
5
6
7
8
mkdir Local_repo 
cd Local_repo
mkdir cuda_lstm_forward_v1
mkdir cuda_lstm_forward_v2

git init
//列出专案资料夹下的档案和资料夹(-l参数为列出详细资料,-a为列出隐藏资料夹)
ls -la

3. 将repo add到cashed里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
git add . //添加所有文件
[zhipeng @ cuda_repo]# git add cuda_lstm_forward_v1/
[zhipeng @ cuda_repo]# git add cuda_lstm_forward_v2/
[zhipeng @ cuda_repo]# git status
位于分支 master

尚无提交

要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)

新文件: cuda_lstm_forward_v1/00_lstm.cu
新文件: cuda_lstm_forward_v1/BUILD.sh
新文件: cuda_lstm_forward_v1/cuda_lstm_forward.cc
新文件: cuda_lstm_forward_v2/00_lstm.cu
新文件: cuda_lstm_forward_v2/BUILD.sh
新文件: cuda_lstm_forward_v2/cuda_lstm_forward.cc
新文件: cuda_lstm_forward_v2/cuda_lstm_forward.so
新文件: cuda_lstm_forward_v2/lib00_lstm.so

未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)

.DS_Store
1
2
//未commit时使用,即可恢复到档案尚未加入暂存区
$ git rm --cached test.cc
  • Cashed的作用:需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改,即下一步

4. 提交和撤回

1
2
3
4
//比较现在档案和上次commit之间的差异,也就是说你做了哪些修改
$ git diff
// -m为输入commit message,也就是说这个commit内做了哪些事情
$ git commit -m "LSTM的加速,v1通用v2定制"
1
2
3
git支持相对引用^
//HEAD^的意思是上一个版本,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
git reset --soft HEAD^

–mixed
意思是:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作
这个为默认参数,git reset –mixed HEAD^ 和 git reset HEAD^ 效果是一样的。

–soft
不删除工作空间改动代码,撤销commit,不撤销git add .

–hard
删除工作空间改动代码,撤销commit,撤销git add .

注意完成这个操作后,就恢复到了上一次的commit状态。

顺便说一下,如果commit注释写错了,只是想改一下注释,只需要:
git commit –amend

总结:

  • HEAD指向的版本就是当前版本,因此,Git允许我们在已commit的版本的历史之间穿梭,使用命令git reset --hard commit_id

  • git checkout -- filename的作用是把filename文件在工作区的修改撤销到最近一次git add 或 git commit时的内容

  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

强制修改分支位置

HEAD 通常情况下是指向分支名的(如 bugFix)。Git用master指向最新的提交,再用HEAD指向master

可以分离HEAD退回到历史版本但不改变master指向进行测试,然后新建分支保存此次测试或修改。

我使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交。例如:

1
git branch -f main HEAD~3

上面的命令会将 main 分支强制指向 HEAD 的第 3 级父提交。

5. 将repository 做本机和远端的连结

1
2
<remote网址>+.git
git remote add origin https://github.com/MintLucas/Cuda_lstm_forward.git
1
2
//将本地端程式push到远端档案库<remote name>/<branch name>分支
$ git push -u origin master

参数-u等同于--set-upstream,只要成功设定好upstream后,第二次以后要上传分支时,就只需要透过git push就可以了,事实上,$ git push -u origin master可以拆解成

1
2
3
$ git push origin master 
$ git checkout master
$ git branch -u origin/master
  • 创建+切换分支:git checkout -b <name>或者git switch -c <name>
  • 合并某分支到当前分支:git merge <name>
  • 删除分支:git branch -d <name>

6. 文件删除

1
2
3
git rm test.txt
rm 'test.txt'
git commit -m "remove test.txt"

如果误删,使用git checkout -- <filename>可从远端恢复

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

7. 远端创建与删除新分支

从远端clone代码,又不想覆盖之前的master代码,就创建新分支全部提交到新分支上。

1
2
3
4
5
6
7
8
9
//先在本地创建,才能远程推送
git checkout -b zhipeng
//在远端创建新分支
git push --set-upstream origin zhipeng

//删除本地分支
git branch -d [branchname]
//删除远端分支
git push origin --delete [branchname]

提高Github Clone速度

1. 用 git 内置代理,直接走系统中运行的代理工具中转,比如,你的 SS 本地端口是 1086(一般port均为1080,查看方法ShadowSocks偏好设置高级),那么可以如下方式走代理:

1
2
git config --global http.proxy socks5://127.0.0.1:1086
git config --global https.proxy socks5://127.0.0.1:1086

vim ~/.gitconfig,手动添加

1
2
3
4
4 [http]
5 proxy = socks5://127.0.0.1:1086
6 [https]
7 proxy = socks5://127.0.0.1:1086

2. 此外,git clone或者git push特别慢,并不是因为 http://github.com 的这个域名被限制了。而是 http://github.global.ssl.fastly.Net 这个域名被限制了。那么可以在hosts文件里进行绑定映射。

具体步骤如下:

在terminal输入命令并输入开机密码,Enter确认

1
sudo vi /etc/hosts

然后依旧在vim上编辑,命令如下

1
2
151.101.72.249 http://global-ssl.fastly.Net
192.30.253.112 http://github.com

3. 最后如果clone过大文件需要增加缓存

git config --global http.postBuffer 24288000

4. 取消全局代理

git config --global --unset http.proxy

git config --global --unset https.proxy

老玩家直接看这里总结

Git global setup

git config --global user.name "zhipeng.li_sx"

git config --global user.email "zhipeng.li_sx@aispeech.com"

Create a new repository

git clone https://git.aispeech.com.cn/zhipeng.li_sx/Cuda_lstm_forward.git cd Cuda_lstm_forward

touch README.md

git add README.md

git commit -m "add README"

git push -u origin master

Existing folder or Git repository

cd existing_folder

git init

git remote add origin https://git.aispeech.com.cn/zhipeng.li_sx/Cuda_lstm_forward.git git add . git commit git push -u origin master

从远端更新

git pull origin master注意会直接和本地合并

git pull --rebase不会合并本地

1
git checkout . #本地所有修改的。没有的提交的,都返回到原来的状态

拉取远程某个分支

先查看远程所有分支

git branch -a

git checkout -t origin/offline_unite_puncsmooth

作用是checkout远程的分支,在本地创建分支,并切换到本地分支

撤回提交版本的reflog

代码库有更新以及本地有更新的解决方法

ssh管理

ssh公匙(id_rsa.pub文件)用来加密,在服务端github或gitlab配置,ssh私匙配在本机用来解密

1. 清除 git 的全局设置(针对已安装 git)

若之前对 git 设置过全局的 user.nameuser.email
类似 (用 git config --global --list 进行查看你是否设置)

1
2
$ git config --global user.name "你的名字"
$ git config --global user.email "你的邮箱"

必须删除该设置,顺便删除代理等

1
2
3
4
5
6
7
8
9
10
$ git config --global --unset user.name "你的名字"
$ git config --global --unset user.email "你的邮箱"
git config --global --unset http.proxy

执行到这儿一般就可以了,下面是mac下配置git密码存储方式
git config -l |grep credential.helper#查看当前存储方式
显示:credential.helper=osxkeychain
git config --system --unset credential.helper#重置记录的密码
git config --global credential.helper store#储存在磁盘
git config --global credential.helper osxkeychain#储存在钥匙串
2. 生成新的 SSH keys

-f指定文件路径,-c注释

1
2
ssh-keygen -t rsa -C "945906741@qq.com" -f ~/.ssh/github_rsa
ssh-keygen -t rsa -C "zhipengxxx" -f ~/.ssh/gitlab_rsa

直接回车3下,什么也不要输入,就是默认没有密码。

完成后会在~/.ssh / 目录下生成以下文件

  • gitlab_rsa.pub
  • gitlab_rsa
  • github_rsa.pub
  • github_rsa
3.添加识别 SSH keys 新的私钥
1
亲测Mac下,新增一个 id_rsa.gitee,没加进去 也识别到了。 所以此步骤可忽略,如有问题删除所有密钥 重新按步骤操作一遍。

默认只读取 id_rsa,为了让 SSH 识别新的私钥,需要将新的私钥加入到 SSH agent 中

1
2
3
$ ssh-agent bash
$ ssh-add ~/.ssh/gitlab_rsa.pub
$ ssh-add ~/.ssh/github_rsa.pub
4. 多账号必须配置 config 文件(重点)

若无 config 文件,则需创建 config 文件

1
$ touch ~/.ssh/config

config 里需要填的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Read more about SSH config files: 
#User zhipeng
Host *
ServerAliveInterval 60
# ClientAliveCountMax 3
# gitlab
Host gitlab
HostName git.intra.xxx.com
User git
IdentityFile ~/.ssh/gitlab_rsa
# githab
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_rsa
5. 当仍提示输密码并且一直不对时,可能是git access token的问题

多人协作的提交(source Tree)

  1. 新建自己的分支zhipeng

  2. 在自己分支写好代码,右键master选择合并master到zhipeng

  3. pycharm项目中右键compare with master,解决冲突,就是从左(远端更新)迁移右(本地)操作

    或自己分支下git pull –rebase origin/master,同样解决冲突

  4. 本地已是解决冲突后的新分支,切到master二次检查,Pull一下然后compare with zhipeng

  5. 无误后gitlab创建merge申请

使用 rebasemerge 的基本原则

  1. dev分支更新master分支,然后继续开发的时候使用 rebase
  2. master分支合并dev分支内容的时候使用 merge
  3. 更新当前分支的内容时一定要使用 --rebase 参数

例如现有上游分支 master,基于 master 分支拉出来一个开发分支 dev,在 dev 上开发了一段时间后要把 master 分支提交的新内容更新到 dev 分支,此时切换到 dev 分支,使用 git rebase master

等 dev 分支开发完成了之后,要合并到上游分支 master 上的时候,切换到 master 分支,使用 git merge dev

  • Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

Rebase相关的要点有这几个:

  1. 在自己的分支上做Rebase;
  2. 要Rebase正确的目标分支,注意这个目标分支不是你的远程分支,这个地方经常有人犯错;
  3. Rebase要常做,以避免出现冲突,或者冲突的难度增加;
  4. 在合入代码之前,一定要最后做一次Rebase再Merge;
  5. 最好用Squash Merge, 添加正确的提交消息;
  6. 不要在主分支上做Rebase;
  7. 尽量不要force push;

在主分支上应该rebase吗? 怎么去做rebase?

首先,我要强调一下,在主分支上不要做rebase。这是因为如果你在主分支上做了rebase,如果你是第1次push可能没有问题,但是如果别的人也做了一个rebase,这个时候就导致你的主分支上有两个不同的head,这个时候如果想再push的话就存在问题了。

如果一切可控的话,你可以非常粗暴的使用强制push。但是如果团队成员比较多,会导致这样的操作会冲掉其他已经进来的提交。

除非万不得已,我们坚决不能在主分支上去做rebase。

接下来说一个正确使用rebase的场景。在接到一个任务以后,我们会在主分支上最新的节点处提交上创建一个新的分支。在新的分支上,我们会不断的进行新的提交,直到完成这个分支任务。

到这个时候,我们想创建一个merge request或者pull request,在此之前,我们首先要做的就是rebase,rebase选的目标分支是我们的主分支。

完成这次rebase操作以后,我们就可以创建mr或者pr了。在审查过程中可能有很多修改意见,修改完成以后需要先
rebase再push。如此反复几次,mr或者pr审批通过。此时要做一次squash merge把数次提交打包合成一个到主分支上。