Git 简介

Git 使用简易指南

  • Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
  • Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
  • Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

Git 与 SVN 区别

  • GIT是分布式的,SVN不是:这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。
  • GIT把内容按元数据方式存储,而SVN是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。
  • GIT分支和SVN的分支不同:分支在SVN中一点不特别,就是版本库中的另外的一个目录。
  • GIT没有一个全局的版本号,而SVN有:目前为止这是跟SVN相比GIT缺少的最大的一个特征。
  • GIT的内容完整性要优于SVN:GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

Git 命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 创建版本库
git clone <url>                          //克隆远程版本库
git init                                 //初始化本地版本库

# 修改和提交
git status                               //查看状态
git diff                                 //查看变更内容
git status                               //跟踪所有改动过的文件
git add <file>                           //跟踪指定的文件
git mv <old> <new>                       //文件改名
git rm <file>                            //删除文件
git rm --cached <file>                   //停止跟踪文件但不删除
git commit -m "message"                  //提交所有更新过的文件及描述
git commit --amend                       //修改最后一次提交

# 查看提交历史
git log                                  //查看提交历史
git log -p <file>                        //查看指定文件的提交历史
git blame <file>                         //以列表形式查看指定文件的提交历史

# 撤销
git reset --hard HEAD                    //撤销工作目录中所有未提交文件的修改内容
git checkout HEAD <file>                 //撤销指定的未提交文件的修改内容
git revert <commit>                      //撤销指定的提交

# 分支与标签
git branch                               //显示所有本地分支
git checkout <branch/tag>                //切换到指定分支或标签
git branch <new-branch>                  //创建新分支
git branch -d <branch>                   //删除本地分支
git tag                                  //列出所有本地标签
git tag <tagname>                        //基于最新提交创建标签
git tag -d <tagname>                     //删除标签

# 合并与衍合
git merge <branch>                       //合并指定分支到当前分支
git rebase <branch>                      //衍合指定分支到当前分支

# 远程操作
git remote -v                            //查看远程版本库信息
git remote show <remote>                 //查看指定远程版本库信息
git remote add <remote> <url>            //添加远程版本库

git fetch <remote>                       //从远程库获取代码
git pull <remote> <branch>               //下载代码及快速合并
git push <remote> <branch>               //上传代码及快速合并
git push <remote> :<branch/tag-name>     //删除远程分支或标签
git push --tags                          //上传所有标签

Git 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# git ssh公钥
ssh-keygen -t rsa -C "laijingwei1993@163.com"

# 保存 git 账号密码,避免每次 push 重复输入
git config --global credential.helper store

# 全局配置
git config --global user.email "laijingwei1993@163.com"
git config --global user.name "赖经纬"

# 禁用自动转换换行符 (LF will be replaced by CRLF in)
git config --global core.autocrlf false

# git log 中文乱码
git config --global core.quotepath false
git config --global gui.encoding utf-8
git config --global i18n.commit.encoding utf-8
git config --global i18n.logoutputencoding utf-8
export LESSCHARSET=utf-8

# 变量添加到 Windows 环境变量

Git Fork 仓库更新

1
2
3
4
5
# 将别人的仓库添加到你的上游远程,通常命名为upstream
git remote add upstream http://192.168.1.100:3000/laijw/docsify-sdsf.git && git fetch upstream

# 合并到 master
git checkout master && git merge upstream/master

Git 提交三部曲

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
git add .
git commit -m "update"
git push origin master

# 首次提交远程仓库
git push -u origin master

# 当本地与远程分支均为默认分支名称时即本地为master,远程分支为origin
git push

# 删除本地缓存,通常用于修改 .gitignore 后
git rm -r --cached .

# 重写 git 历史,通常用于 git clone --depth 1 <..> 后
git filter-branch -- --all

Git 查看代码贡献量

1
2
3
4
5
6
7
8
# 查看git上个人代码量
git log --author="赖经纬" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -

# 统计每个人的增删行数
git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done

# 查看仓库提交者排名前 5
git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5

Git 本地临时服务器

1
2
3
4
mkdir test.git && cd test.git
git init --bare
git remote add origin D:\test.git
git push

Git 部署

1
2
3
4
5
6
# CentOS部署
cd /www/wwwroot/laijw.mxnt.net
git pull origin master

# 当本地与远程分支均为默认分支名称时即本地为master,远程分支为origin
git pull

git clone 加速

通过淘宝代理

1
2
https://github.com/spf13/spf13-vim.git
https://github.com.cnpmjs.org/spf13/spf13-vim.git

通过本地代理

1
2
git config --global http.https://github.com.proxy socks5://127.0.0.1:1080
git config --global https.https://github.com.proxy socks5://127.0.0.1:1080

git submodules

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 在 Linux 下执行
git rm --cached addons/Wechat
git submodule add http://git.huizhouyiren.com/mirrors/Wechat.git addons/Wechat
git add .
git commit -m "2020/04/28 星期二 16:31:01 赖经纬"
git push origin master

# 克隆有 git 子模块的仓库
git clone --recurse-submodules http://git.huizhouyiren.com/php/yirenframe.git

# 批量更新子模块仓库
git submodule foreach git submodule update

Commitizen

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
npm install -g commitizen
cd .git

# npm
commitizen init cz-conventional-changelog --save-dev --save-exact

# yarn
commitizen init cz-conventional-changelog --yarn --dev --exact

git add .
git cz
git push

gitignore

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#               表示此为注释,将被Git忽略
*.a             表示忽略所有 .a 结尾的文件
!lib.a          表示但lib.a除外
/TODO           表示仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/          表示忽略 build/目录下的所有文件,过滤整个build文件夹;
doc/*.txt       表示会忽略doc/notes.txt但不包括 doc/server/arch.txt
 
bin/:           表示忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件
/bin:           表示忽略根目录下的bin文件
/*.c:           表示忽略cat.c,不忽略 build/cat.c
debug/*.obj:    表示忽略debug/io.obj,不忽略 debug/common/io.obj和tools/debug/io.obj
**/foo:         表示忽略/foo,a/foo,a/b/foo等
a/**/b:         表示忽略a/b, a/x/b,a/x/y/b等
!/bin/run.sh    表示不忽略bin目录下的run.sh文件
*.log:          表示忽略所有 .log 文件
config.php:     表示忽略当前路径的 config.php 文件
 
/mtk/           表示过滤整个文件夹
*.zip           表示过滤所有.zip文件
/mtk/do.c       表示过滤某个具体文件

被过滤掉的文件就不会出现在git仓库中(gitlab或github)了,当然本地库中还有,只是push的时候不会上传。

需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中,如下: !*.zip !/mtk/one.txt

唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。为什么要有两种规则呢? 想象一个场景:假如我们只需要管理/mtk/目录中的one.txt文件,这个目录中的其他文件都不需要管理,那么.gitignore规则应写为:: /mtk/* !/mtk/one.txt

假设我们只有过滤规则,而没有添加规则,那么我们就需要把/mtk/目录下除了one.txt以外的所有文件都写出来! 注意上面的/mtk/*不能写为/mtk/,否则父目录被前面的规则排除掉了,one.txt文件虽然加了!过滤规则,也不会生效!

还有一些规则如下: fd1/* 说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;

/fd1/* 说明:忽略根目录下的 /fd1/ 目录的全部内容;

/* !.gitignore !/fw/ /fw/* !/fw/bin/ !/fw/sf/ 说明:忽略全部内容,但是不忽略 .gitignore 文件、根目录下的 /fw/bin/ 和 /fw/sf/ 目录;注意要先对bin/的父目录使用!规则,使其不被排除。