git 实战使用

374 阅读21分钟

git config 与git中一些选项参数解释

查看当前git的配置

git config --list

这里需要注意一下的是,当你是全局执行了这条查看命令的时候,会发现git的config信息很少,那是因为他只显示了全局的一些配置,一些项目的git仓库配置需要进入到对应的项目目录下去执行才能看得到

配置git用户名和邮箱

git配置用户名和邮箱分全局配置和局部配置,可以全局配置邮箱和用户名也可以局部根据项目去配置不同的用户名和邮箱
1、全局配置

git config --global user.name 'wujianrong'
git config --global user.email 'wjr_1532@163.com'

附:除了邮箱,我们也可以用ssh key来代替账号密码的使用,生成ssh key的方法

ssh-keygen -t rsa -C "wjr_1532@163.com"

执行完命令后在ssh目录会有两个文件,私钥 (id_rsa) 与公钥 (id_rsa.pub),公钥上传到对应的ssh服务器,当本地的登录ssh的时候就会去校验这服务器上的公钥和本地的私钥是否吻合,吻合即可登录(再啰嗦一下,rsa其实是一种密码算法,还有一种是dsa,有兴趣可以自行查找)
打开ssh目录查看

cd ~/.ssh/ 
open .

2、局部配置(对当前项目git仓库配置) 先进入到对应的项目的根目录

git config user.name 'wujianrong'
git config user.email 'wjr_1532@163.com'

配置完之后可以运行git config --list检查下是否已经更换成功

名字和邮箱是在什么时候看到得到呢
我们在执行git log的时候提交记录就会看得到这是谁提交的,邮箱是多少

多账号配置

我自己平时工作使用的是个人的电脑,经常会有一些问题,我个人的git和公司账号的git要来回切换,那我们该怎么配置多账号的git使用呢

  1. 生成sshkey
# windoWs的ssh目录 一般在 c盘/用户/.ssh  mac 直接cd ~/.ssh即可
cd ~/.ssh
ssh-keygen -t rsa -C "xxx@163.com"
#设置文件名,自动生成私钥和公钥(.pub)
Enter file in which to save the key (/c/Users/icecr/.ssh/id_rsa): id_rsa_github
#将ssh key添加到SSH agent中 
ssh-add ~/.ssh/id_rsa_github

执行ssh-add时出现Could not open a connection to your authentication agent
先执行**ssh-agent bash**

  1. 在github的profile中添加新的公钥,将.ssh目录下对应的id_rsa_github.pub中的内容拷到Key中

  2. 在~/.ssh下新增config文件,下面是我目前配置了的三个账号分别是github、gitee和公司内部的gitlab

# github
Host github.com
HostName github.com
User wjr_1532@163.com
IdentityFile ~/.ssh/id_rsa_github
# 加载到 ssh-agent 
AddKeysToAgent yes
# 添加到用户钥匙串
UseKeychain yes

# gitee
Host gitee.com
HostName gitee.com
User wjr_1532@163.com
IdentityFile ~/.ssh/id_rsa_gitee
# 加载到 ssh-agent 
AddKeysToAgent yes
# 添加到用户钥匙串
UseKeychain yes

# md
Host 172.28.1.6
HostName 172.28.1.6
User wujr@pvc123.com
IdentityFile ~/.ssh/id_rsa_md
# 加载到 ssh-agent 
AddKeysToAgent yes
# 添加到用户钥匙串
UseKeychain yes
  1. 通过ssh -T 测试是否连接成功

image.png

配置git命令别名(alias)

配置别名的作用是为了能减少我们敲命令的代码量,提高效率,比如:git push 我可以给push起一个别名,只使用git ps就可以了

git config --global alias.ps push

git 配置的影响范围

git配置级别主要有三种:
git config --list --global/system/local
1、系统级别

git config --system

2、全局

git config --global

3、局部

git config
或者(在git仓库下默认就是局部配置,不带--local也是局部)
git config --local

附: git的配置读取顺序
优先级:
--local > --global > --system

git中一些选项解释:

-d --delete:删除

-D --delete --force的快捷键

-f --force:强制

-m --move:移动或重命名

-M --move --force的快捷键

-r --remote:远程

-a --all:所有



git clone 与git branch与检出分支

克隆项目 git clone(默认master分支)

git clone xxx(仓库地址)

git clone默认是克隆master分支上的代码
我们在克隆下来的项目根目录中执行查看分支

git branch 

也会发现克隆下来的只有一个master分支

克隆项目指定分支 git clone

比如克隆dev分支(这里的克隆和检出(checkout)多个分支不是一个操作,需要区分,克隆不同的分支,是在本地有多个目录,分别存放不同的分支,检出了多个分支之后是可以在同一个目录里面切换分支)

git clone -b dev xxx(仓库地址)

查看分支

如果在克隆的时候不知道有什么分支,我们可以查看下仓库有哪些分支

查看本地分支
git branch 

查看远程分支
git branch -r

查看本地和远程的所有分支
git branch -a

新建分支
git branch <branchname> 

删除分支
git branch -d <branchname> 

删除远程分支,删除后还需推送到服务器
git branch -d -r <branchname>
git push origin:<branchname>

重命名本地分支
git branch -m <oldbranch> <newbranch>

检出/切换分支

检出分支主要是通过使用git checkout命令去检出(git checkout不仅仅只有检出分支的功能,后面会详细介绍,这里只做检出分支功能的讲解)

git checkout xxx(分支名)
如果本地已经有了该分支,就会直接切换到对应的分支
git checkout -b xxx(本地分支名) zzz(远程分支名)
检出远程分支,并且在本地建立分支来跟踪


git tag

git tag一般用于标记项目的版本
比如一个app今天上线了个1.0.1的版本,那么我们需要在上线的最后一次提交打上一个标签tag,如果我们在上线下一个版本的时候有紧急的bug一时修复不了,需要回退一个版本的时候,这个时候我们就可以通过tag找到当时的git记录的版本,或者是用于查找版本线的代码审查,排查项目是从哪个版本开始就有问题

创建标签

Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。
轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。但是如果你只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,那么也可以用轻量标签。

附注标签

在 Git 中创建附注标签十分简单。 最简单的方式是当你在运行 tag 命令时指定 -a 选项:

打上v1.4的标签,并且带上标签信息 my version 1.4
$ git tag -a v1.4 -m "my version 1.4"
查看标签,可发现标签就已经打上了
$ git tag
v0.1
v1.3
v1.4

查看指定标签信息
git show v1.4

后期打标签
git tag -a v1.2 9fceb02(9fceb02是commit id)
//打了标签之后要推送到远程
git push --tag
//删除标签
git tag -d v1.4 
//如果标签已经推送到了远程了,需要先删除本地标签,再通过refs推送到远程
git tag -d v1.4 
git push origin :refs/tags/v1.4


git status 与 git diff

文件状态的类型

1、已追踪文件 在仓库之前的版本快照中包含文件的记录,在用户工作一段时间后,这些文件同样能被追踪到(文件的修改、删除) 2、未追踪文件 在仓库之前没有包含的(文件的新建)

状态流程图:
Untracked: 没有追踪到的文件,比如刚刚新建的文件,可通过add命令添加到暂存区
Unmodified: 没有修改的的文件 通过修改就会到了已修改的状态 如果删除了就会变成Untracked未追中状态 Modified: 已经修改了的文件状态 同样可以通过add命令添加到暂存区
Staged: 暂存区,在暂存区里面的文件通过commit,提交了之后,暂存区就会清空,文件回到了Unmodified状态

git status

git status 主要查看所有文件具体的更新内容,通过git status 命令显示出来的文件共有三种状态,分别是
1、已添加暂存区,待提交(执行了git add 后)
2、已修改,未暂存 处于Modified状态
3、未追踪文件,一般是指新增的文件

通过增删改来举例一下各个状态:

1、首先建好了一个空的仓库,并且执行了git status查看一下

可以看到仓库是没有任何修改的,处于master分支
ls 仓库当前只有3个文件

2、执行增、删、改文件命令,查看文件的各种状态

  • 增: echo 'hello world' > test1.txt 添加一个test1.txt文件,里面内容为hello world
  • 删: rm -rf README.en.md
  • 改: echo 'hello+++++world' > test.txt
    执行完之后git status查看一波
change not staged for commit:(修改了但是还没暂存提交的文件有  )
删除了README.en.md,修改了test.txt  
Untracked files:(未追踪文件)
新曾了test1.txt   
  • 执行git add test.txt将test.txt添加到暂存区之后再来看看

  • 我们已经将test.txt添加到暂存区了,然后再去修改文件,看看是什么状态 这个时候我们会发现test.txt文件会有两个状态,一个已经在暂存区了,一个是处于已修改过的状态,说明暂存区和本地修改的区是可以独立的,我们可以单独只commit暂存区里面的test.txt,然后push提交,处于本地已修改的文件,我们可以继续编码完成之后再去提交,并不会冲突,但是如果此时直接再将test.txt文件add多一次的话,两次修改的就会合并在暂存区里面

git diff

diff命令主要是用于查看文件的详细修改内容

git diff test.txt

我们可以看到diff命令可以直接查看等到我们的文件修改了什么内容,但是diff命令默认是只能看到本地修改的,如果需要查看暂存区的修改,我们需要执行

git diff staged

git diff主要只是用于本地和暂存区的修改,如果需要查看到所有时间所有状态的修改记录就要使用到git log



git commit与git log

git commit 帮助

git commit功能太多了,先把--help拿出来祭天

git commit --help

接下来再介绍下常用的 git commit 操作

git commit -m message

git commit message是指每次提交编辑的内容信息
commit message的好处:

  • 提供更多可查询的信息,用于排查问题
  • 过滤重要内容(后面的讲到git log的时候会体现)
  • 生成changelog

标准的commit message包括:Header、Body、Footer三部分
一般我们只用到Header
Header的组成:
type(scope): subject 注意:括号和:是英文编码,:后需要带上一个空格
type常用类型如下:

  • feat(feature) 新功能
  • fix 修复bug
  • style 格式
  • docs 文档修改
  • refactor 代码重构
  • chore 项目构建

scope指的是本次修改的影响范围,一般写模块名

subject修改的内容信息

git cz

cz全名:commitizen commit message的整理插件 是git提交信息的一种消息模式
安装

npm install -g commitizen

然后,在项目目录里,运行下面的命令,使其支持Commit message 格式。

commitizen init cz-conventional-changelog --save --save-exact

这样的话以后提交信息的时候就不用git commit了,直接git cz就好了,具体步骤如下 git status -s git add . git cz git push 执行到git cz这一步的时候会出现如下图:

cz了解下即可,实际上我们也的大部分会用一些可视化工具

changelog

changelog是项目迭代过程中一系列的变更记录
一般会描述某一个版本,修复了什么问题,增加了新功能
要生成changelog,首先我们要先安装对应的依赖

npm install -g cz-conventional-changelog

git log 技巧

1、git log --help 帮助命令祭天

2、git log 参数参考

git log 命令支持的选项

-p 按补丁格式显示每个更新之间的差异。

--stat 显示每次更新的文件修改统计信息。

--shortstat 只显示 --stat 中最后的行数修改添加移除统计。

--name-only 仅在提交信息后显示已修改的文件清单。

--name-status 显示新增、修改、删除的文件清单。

--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。

--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。

--graph 显示 ASCII 图形表示的分支合并历史。

--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)

3、git log 常用使用场景

1、log信息一行显示完全
git log --pretty=oneline


2、展示简要的每次提交行数的变化,及其他基本信息。
git logstat
3、展示每次提交详细的代码变化
git log -p
4、根据commit message 信息过滤
git log --grep="commit message"

5、按照文件过滤
git log -- filename

6、按照作者过滤
git log --author="John"
也可以过滤多个作者
git log --author="John\|Mary"


git reset 撤销与git clean 清除

git reset

1、git reset撤销本地commit,还没有push的时候

我们有时候不小心commit一次错误的内容,但是还没有推送的时候,我们可以撤回,如果需要撤回的是最后一次 比如我们最后一次提交的commit message不规范,我们要撤回,但是内容需要保留,也可以根据commitId去撤回

git reset HEAD~  

我们可以发现commit就撤回了,但是我们添加的test4.txt文件还在

2、git reset撤销远程commit,已经push上去了

查看git提交记录
git log --pretty=oneline
wujianrong : ~/Documents/wjr_project/project/git-test-demo #git log --pretty=oneline
8134fe0c1171cfe9322d960a8325ab92d1a7763d (HEAD -> master, origin/master, origin/HEAD) fix(All):git commit 测试
1d9866109ec13a2433348e60b809ffbabe9d2d41 refactor(All): 合并--amend测试
df8f498db024ef2d2b1f1ae78b1c5170b246c3da refactor(All): 合并--amend
93d11b0525135bbcc541147996ac59373be9393f refactor(All): 增删改演示
bee1fc86075775df5c44063ca4721a8ffe90f88b refactor(All): 演示增删改
3ab4fb74b1532307a9a19c6b86a081b84e94b157 feat(All): 新增一个演示文件

这里我们找到对应的commitId,我们这里以回退到93d11b0525135bbcc541147996ac59373be9393f refactor(All): 增删改演示这里为例子(commitId不需要打全部,只要能让git读取到区分就行了,一般取7位数

git reset --hard 93d11b0

reset --hard:重置stage区和工作目录,带上--hard会把工作区和暂存区的内容都抹除掉,所以要谨慎,如果在reset的时候,工作区和暂存区又有需要保留的修改,那么就需要执行
可以看到,在 reset --hard 后,所有的改动都被擦掉了。 reset --soft:保留工作目录,并把重置 HEAD 所带来的新的差异放进暂存区

再查看git提交记录
git log --pretty=oneline

我们就发现已经回退到了对应的commit了,这个时候只是本地回退了,还需要推送到服务器

git push origin master --force
--force是强制覆盖,避免冲突,如果没有重推的情况下,直接git push也是可以的

reset三种模式区别和使用场景

区别:

--hard:重置位置的同时,直接将 working Tree工作目录、 index 暂存区及 repository 都重置成目标Reset节点的內容,所以效果看起来等同于清空暂存区和工作区。

--soft:重置位置的同时,保留working Tree工作目录和index暂存区的内容,只让repository中的内容和 reset 目标节点保持一致,因此原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files)。所以效果看起来就是工作目录的内容不变,暂存区原有的内容也不变,只是原节点和Reset节点之间的所有差异都会放到暂存区中。

--mixed(默认):重置位置的同时,只保留Working Tree工作目录的內容,但会将 Index暂存区 和 Repository 中的內容更改和reset目标节点一致,因此原节点和Reset节点之间的【差异变更集】会放入Working Tree工作目录中。所以效果看起来就是原节点和Reset节点之间的所有差异都会放到工作目录中。

使用场景:

--hard:
(1) 要放弃目前本地的所有改变時,即去掉所有add到暂存区的文件和工作区的文件,可以执行 git reset -hard HEAD 来强制恢复git管理的文件夹的內容及状态;
(2) 真的想抛弃目标节点后的所有commit(可能觉得目标节点到原节点之间的commit提交都是错了,之前所有的commit有问题)。

--soft:
原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files),
所以假如我们之前工作目录没有改过任何文件,也没add到暂存区,那么使用reset --soft后,
我们可以直接执行 git commit 將 index暂存区中的內容提交至 repository 中。为什么要这样呢?这样做的使用场景是:假如我们想合并「当前节点」与「reset目标节点」之间不具太大意义的 commit 记录(可能是阶段性地频繁提交,就是开发一个功能的时候,改或者增加一个文件的时候就commit,这样做导致一个完整的功能可能会好多个commit点,这时假如你需要把这些commit整合成一个commit的时候)時,可以考虑使用reset --soft来让 commit 演进线图较为清晰。总而言之,可以使用--soft合并commit节点。

--mixed(默认):
(1)使用完reset --mixed后,我們可以直接执行 git add 将這些改变果的文件內容加入 index 暂存区中,再执行 git commit 将 Index暂存区 中的內容提交至Repository中,这样一样可以达到合并commit节点的效果(与上面--soft合并commit节点差不多,只是多了git add添加到暂存区的操作);
(2)移除所有Index暂存区中准备要提交的文件(Staged files),我们可以执行 git reset HEAD 来 Unstage 所有已列入 Index暂存区 的待提交的文件。(有时候发现add错文件到暂存区,就可以使用命令)。
(3)commit提交某些错误代码,或者没有必要的文件也被commit上去,不想再修改错误再commit(因为会留下一个错误commit点),可以回退到正确的commit点上,然后所有原节点和reset节点之间差异会返回工作目录,假如有个没必要的文件的话就可以直接删除了,再commit上去就OK了。

git reflog

当我们执行了reset之后,发现我们执行错了,我们需要保留之前的某次commit,这个时候我们就可以通过reflog查看我们需要找回的commit 执行之后我们可以看到我们之前reset撤销的记录实际上也在reflog里面产生了一次新的id,我们可以通过reflog的id撤销我们的reset,但是此时如果我们不想要全部撤回,只想撤回中间的某一次,那么我们就找到需要撤回的id,这里我们以撤回【1d98661 HEAD@{5}: commit (amend): refactor(All): 合并--amend测试】为例子

git reset --hard 1d98661

git log查看后,我们可以发现,我们就把之前的commit拿回来了
git push 推送到服务器

git clean

git clean命令用来从你的工作目录中删除所有没有追踪过的文件 git clean经常和git reset --hard一起结合使用. 记住reset只影响被追踪过的文件, 所以需要clean来删除没有追踪过的文件. 两个命令一起使用,就可以达到完全撤销和清除掉本地的所有修改
git reset在上面介绍过了,这里就不再赘述了

git clean用法

git clean -n 是一次clean的提醒, 告诉你哪些文件会被删除. 不是真正执行删除文件动作, 只是一个提醒

git clean -f 删除当前目录下所有没有track过的文件. 他不会删除.gitignore文件里面指定的文件夹和文件, 不管这些文件有没有被track过

git clean -f 删除指定路径下的没有被追踪过的文件

git clean -df 删除当前目录下没有被追踪过的文件和文件夹

git clean -xf 删除当前目录下所有没有追踪过的文件. 不管他是否是.gitignore文件里面指定的文件夹和文件

git reset --hard和git clean -f 结合使用可以清除掉本地所有文件的修改和添加(未追踪)

git reset --hard
git clean -df
一波操作下去你完全撤销和清除掉本地的所有修改 


git stash 贮藏

git stash

场景1:我们在开发过程中经常会出现一种情况,你在开发a版本的时候,突然测试过来跟你说有个紧急的bug要修复,放在b版本那去,这个时候我们在a版本的分支上开发到一半,不得不要切换到b版本的分支,但是a版本这边开发了一半的代码又不想commit的时候我们该怎么办?
场景2:我们在沉迷开发的时候,在a分支上一顿操作猛如虎之后,发现我们当前开发的内容应该在b分支上,这个时候切分支又切换不过去(两个分支的md5值不相同的时候,切换分支会报错) 这个时候我们就可以用到git stash把当前修改的代码贮藏起来先

例子: 从图片看拿到,我们现在有一个test.txt文件被修改过了,并且我们现在在master分支上,我们现在想把test.txt修改的内容存起来先

git stash

执行完git stash之后,我们再git status会发现,本地的修改已经看不到了,这个时候我们就可以切换到其他分支去干活了

查看我们现在有哪些贮藏
git stash list

通过git stash list,我们可以看到我们贮藏了那些内容,但是显然我们可能看不出具体是什么内容,所以我们在贮藏的时候尽量规范,应该带上贮藏信息去贮藏,方便以后我们回忆内容

带上描述信息贮藏
git stash save "stash messageh"

这个时候我们看到最新的一次贮藏是有带上描述信息的,on master(代表当时贮藏的分支是在master)

查看贮藏修改了什么内容
git stash show :显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{$num},比如第二个 git stash show stash@{1}

git stash show -p : 显示第一个存储的改动,如果想显示其他存存储,命令:git stash show  stash@{$num}  -p ,比如第二个:git stash show  stash@{1}  -p

取出贮藏
git stash apply :应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{$num} , 比如第二个:git stash apply stash@{1} 

git stash pop :命令恢复之前缓存的工作目录,将缓存堆栈中的对应stash删除,并将对应修改应用到当前的工作目录下,默认为第一个stash,即stash@{0},如果要应用并删除其他stash,命令:git stash pop stash@{$num} ,比如应用并删除第二个:git stash pop stash@{1}

git stash apply 和 git stash pop的区别主要在于apply是不会取出了贮藏内容之后,并不会删除贮藏,可以再次取,pop是取了之后就清除了贮藏,不能再次取该次的贮藏

删除贮藏
git stash drop stash@{$num} :丢弃stash@{$num}存储,从列表中删除这个存储

git stash clear :删除所有缓存的stash  

git 忽略文件的使用

git .gitignore文件

.gitignore文件是git读取忽略规则的文件,git通过匹配规则,对仓库下的文件夹和文件不进行跟踪 image.png 如上图所示,忽略掉了node_modules等目录

常见问题:

1、如何忽略已经跟踪过的文件?貌似gitignore没有生效的样子?
如果已经被跟踪过的文件,想要忽略掉,可以先删除git的缓存

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

2、如何跟踪已经被忽略过的文件?
以前被忽略过的文件,现在想要重新跟踪

git rm -r --cached .
git add xxx文件 -f    

add 加上 -f是指强制跟踪,使用-f切记要指定目录或者文件,不要直接根目录下全部强制跟踪

除了强制-f跟踪,也可以通过反向匹配规则来重新跟踪,比如之前忽略掉了node_modules目录,现在想要重新跟踪,那我们只需要在.gitignore文件 “node_modules” 改成 “!/node_modules” 这样就是反向匹配规则,这样一来,node_modules就会重新跟踪,推送过一次,跟踪后,就可以把“!/node_modules”删掉了