Git
介绍
Git 是分布式版本控制系统(Distributed Version Control System - DVCS)。官网:https://git-scm.com/docs
- Workspace:工作区
- Index / Stage:暂存区
- Repository:本地仓库
- Remote:远程仓库
配置单个 SSH-Key
全局配置用户信息
git config --global user.name "your_name"
git config --global user.email "your_email"
# 查看全局的用户名
git config --global user.name
# 查看全局的邮箱
git config --global user.email
生成 SSH 密钥
ssh-keygen -t rsa -C "youremail@email.com"
在 Mac 终端里查看密钥:vim ~/.ssh/id_rsa.pub
,然后将公共密钥添加进 github 或者 gitlab 里。或者直接复制密钥:
pbcopy < ~/.ssh/id_ras.pub
测试连接是否成功: ssh -T git@github.com
如果提示:Hi Ivanzgh! You've successfully authenticated, but GitHub does not provide shell access.
说明连接成功了
查看当前仓库配置信息
git config --local --list
查看全局配置信息
git config --global --list
配置多个 SSH-Key
如果想将个人的 GitHub 密钥和公司的密钥区分开来,就需要配置多个 SSH Key
1、删除本地的 SSH
这个步骤不是必需的,如果想全部重来就可以使用。打开终端输入cd ~/.ssh
,如果顺利进入到 .ssh
文件夹,使用命令:
cd ..
rm -r .ssh
2、清空默认的用户名和邮箱
查看已配置的 git 列表 git config --list
如果没有默认的用户名和邮箱就忽略,否则执行以下命令重置:
git config --global --unset user.name
git config --global --unset user.email
3、创建新的 SSH
打开终端输入cd ~/.ssh
,如果没有 .ssh
目录,先创建该目录
mkdir ~/.ssh
在 .ssh
目录下生成 ssh-key
,填入自己的邮箱地址
ssh-keygen -t rsa -C "youremail@email.com"
然后会要输入 SSH key 的名字,如id_rsa
、id_rsa_github
随你自定义,然后不要输入密码,一直回车就行。
然后配置其他的 SSH Key,如 gitlab,邮箱也可以变更
ssh-keygen -t rsa -f ~/.ssh/id_rsa_gitlab -C "youremail@email.com"
然后同上要输入名字,一路回车
4、将私钥添加到 ssh-agent 信任列表
ssh-add ~/.ssh/id_rsa
如果出现Identity added: /Users/zgh/.ssh/id_rsa (youremail@email.com)
,表示添加成功了。
继续添加另一个ssh-add ~/.ssh/id_rsa_gitlab
关于ssh-agent
信任列表:
# 查看信任列表
ssh-add -l
# 清空所有的ssh key
ssh-add -D
5、配置 config 文件
终端输入open ~/.ssh/
,看看有没有 config 文件,文件没有后缀,如果没有就新建一个。
新建 config 文件:
cd ~/.ssh
touch config
然后可以在终端修改vim config
,也可以直接打开 config 文件修改,Mac 下通过文本编辑打开。
cd ~/.ssh
vim config
内容如下:
Host github
HostName github.com
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
Host gitlab
HostName gitlab.com
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa_gitlab
- 以
#
开头的是注释,会被忽略 Host
: 机器别名,用于标识特定的配置HostName
: 主机名,一般为 ip 或者主机域名IdentityFile
: 私钥证书文件位置,默认位置是~/.ssh/id_rsa
,如果采用默认证书,可不填此项User
:用于连接的用户名Port
: SSH 访问主机的端口号,默认是 22 端口
6、将公钥添加到远程仓库
将公钥复制到剪贴板,然后去添加到各个远程仓库
pbcopy < ~/.ssh/id_rsa.pub
# gitlab
# pbcopy < ~/.ssh/id_rsa_gitlab.pub
查看公钥内容:vim ~/.ssh/id_rsa.pub
7、测试连接
ssh -T git@github.com
如果 config 配置的用户名是其他的,如 zgh,那么在@
后面还需加上用户名,克隆的时候也需要加上
ssh -T git@zgh.github.com
然后在不同的仓库下设置局部的用户名和邮箱
git config user.name "yourname"
git config user.email "youremail"
概念
HEAD
- HEAD 是指向当前 commit 的引⽤,它具有唯⼀性,每个仓库中只有⼀个 HEAD。在每次提交时它都会⾃动向前移动到最新的 commit
- branch 是⼀类引⽤。HEAD 除了直接指向 commit,也可以通过指向某个 branch 来间接指向 commit。当 HEAD 指向⼀个 branch 时,commit 发⽣时,HEAD 会带着它所指向的 branch ⼀起移动
常用命令
克隆远程仓库
git clone 仓库地址
rebase
git merge 和 git rebase 都是用于分支合并,关键在 commit 记录的处理上不同:
- git merge 会新建一个新的 commit 对象,然后两个分支以前的 commit 记录都指向这个新 commit 记录。这种方法会保留之前每 个分支的 commit 历史。
- git rebase 会先找到两个分支的第一个共同的 commit 祖先记录,然后将提取当前分支这之后的所有 commit 记录,然后将这个 commit 记录添加到目标分支的最新提交后面。经过这个合并后,两个分支合并后的 commit 记录就变为了线性的记录了。
总之:
- git merge 会产生无关的提交记录
- git rebase 会让历史记录干净整洁,不要在公共分支上使用
多个 commit 合并提交
假设你写完了一个 A 功能,执行git add .
、git commit
,然后发现还要改动一下,如果继续 add、commit,那么在 push 的时候会有 2 条提交记录,其实你只是完成了一个功能,保留一条提交信息才是简洁明了的。这时就需要将第一次 commit 撤销,回到暂存区,然后再 commit 提交,就只有一条记录了
修复最新提交的错误
在提交时,如果加上 --amend
参数,则不会在当前 commit 上增加 commit,⽽是会把当前 commit ⾥的内容和暂存区⾥的内容合并起来后创建⼀个新的 commit,⽤这个新的 commit 把当前 commit 替换掉,对最新⼀条 commit 进⾏修正
git commit --amend
HEAD
描述 | |
---|---|
HEAD | 当前版本 |
HEAD^ | 上一个版本 |
HEAD^^ | 上上一个版本 |
HEAD^^^ | 上上上一个版本 |
HEAD~n | 回撤 n 个版本,这种也是更加方便的 |
如:
# 切换到上一个版本
git checkout HEAD^
# 切换到上上上个版本
git checkout HEAD~3
撤销最新的提交
git reset [--soft | --mixed | --hard] [HEAD]
git reset --hard ⽬标commit
git reset --hard HEAD^
stash 临时存放⼯作区的改动
stash 指令可以把⼯作区的内容全部放在本地的⼀个独⽴的地⽅,它不会被提交和删除。
假设你当前正在开发中,突然需要优先干其他工作,又不想 add 和 commit,这时就可以将当前内容放入临时区,等其他工作干完了,再切换回你的分支,将临时区的内容取出来,就可以继续之前的工作了。
# 保存当前工作区的修改
git stash
# 保存当前工作区的修改,可以省略 push 参数
git stash push
# 保存当前工作区的修改,并添加说明信息
git stash push -m 'message'
# 已废弃,用于添加说明信息
git stash save "message"
# 没有被 track 的⽂件,即从来没有被 add 的⽂件不会被 stash
# 可以加上 -u 参数,它是 --includeuntracked 的简写
git stash -u
# 查看储存区所有提交列表
git stash list
# 应用最新的stash,并将其从stash列表中删除
# git stash push 的逆操作
git stash pop
# 应用最新的stash,并保留stash的副本
git stash apply
# 如果有多个stash,想要应用特定的stash,其中n是stash的索引号,下标从0开始
git stash apply stash@{n}
# 从存储条目列表中删除单个存储条目
git stash drop stash@{n}
# 清空所有的stash
git stash clear
常用的命令:
# 放进去
git stash
# 放进去,并添加说明信息
git stash push -m 'message'
# 取出来,并从列表中删除
git stash pop
# 如果有多个,要取指定的
git stash pop stash@{n}
# 查看列表
git stash list
暂存区
# 添加单个文件到暂存区
git add 文件名
# 将当前目录下的所有文件都添加到暂存区
git add .
# 将当前仓库的所有文件都添加到暂存区
git add -A
# 从暂存区撤销文件,工作区的代码还在
git rm --cached 文件名
提交到本地仓库
# -m 后表示提交信息
git commit -m 'xx'
删除本地仓库的文件
# 删除单个文件
git rm 文件名
# 删除目录
git rm -r 目录名
拉取远程仓库
# 如果当前分支和远程分支已经建立了联系
git pull
# 拉取指定远端分支合并到本地当前分支
git pull origin 分支名
git pull
命令是 git fetch
和 git merge
两个操作的组合。
pull 的内部操作其实是把远程仓库取到本地后(使⽤的是 fetch),再⽤⼀次 merge 来把远端仓库的新 commits 合并到本地。
提交到远程仓库
git push
# 初次提交,需要和远程仓库先建立联系
git push --set-upstream origin 分支名
查看仓库当前状态
git status
查看历史记录
git log
# 查看详细改动,-p 是 --patch的缩写
git log -p
# 查看大致改动
git log --stat
查看 commit
# 看当前的commit
git show
# 看任意一个commit
# 在 show 后⾯加上这个 commit 的引⽤(branch 或 HEAD 标记)或它的 SHA-1 码
git show 4fc58ba6808329d98146be8543aa14112c632213
# 看指定commit的指定文件
# 在 commit 的引⽤或 SHA-1 后输⼊⽂件名
git show 4fc58ba6808329d98146be8543aa14112c632213 test.txt
查看未提交的内容
# 查看⼯作区和暂存区的区别
git diff
# 查看暂存区和上⼀条 commit 的区别
git diff --staged(或 --cached)
# 查看⼯作区和上⼀条 commit 的区别
git diff HEAD
- 第一条命令表示:如果你现在把所有⽂件都 add,你会向暂存区中增加哪些内容
- 第二条命令表示:如果你输⼊ git commit,你将会提交什么
- 第三条命令表示:如果你把所有⽂件都 add, 然后 git commit,你将会提交什么。是上⾯两条命令的内容相加
查看 origin 的详细信息
git remote show origin
查看本地关联的仓库地址
git remote -v
仓库备份
# 添加备份仓库
git remote set-url --add origin http://xxx.git
分支
新建分支
git branch 分支名称
切换分支,并更新工作区
git checkout 分支名称
新建分支,并切换到该分支
等同于以上两条命令
git checkout -b 分支名称
基于远程仓库创建新分支
# 基于远程仓库创建新分支
git branch branch_name remote_name/branch
# 基于远程仓库创建新分支并且切换到新分支
git checkout -b branch_name remote_name/branch
如基于远程 develop 分支创建开发分支feture-test:git checkout -b feture-test origin/develop
,origin 是远程仓库的别名
这样就可以不用创建本地的 develop 分支
- 在本地创建 develop 分支,基于它创建开发分支,每次提交前拉取最新的 develop 分支,然后合并进开发分支,最后提交
- 基于远程分支创建新分支,本地不用维护 develop 分支,每次提交前先拉取最新的代码,然后提交。这里执行
git pull
就是拉取远程 develop 分支的代码
git add .
git commit -m '提交信息'
git pull
git push
查看分支
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 查看本地远程所有分支
git branch -a
# 查看本地分支所关联的远程分支
git branch -vv
合并分支
比如你的代码提交之前需要合并最新的 develop 分支,则要做如下操作:
- 切到 develop 分支,git pull 拉一下最新代码
- 切回开发分支,执行
git merge develop
合并一下 develop 代码
git merge 被合并的分支名称
## 撤销合并到执行合并以前的状态
git merge --abort
## 如果合并后的提交还停留在本地Git库,没有被推送到远程
git reset --hard HEAD
删除分支
# -d 表示delete,用于已经合并过的分支
git branch -d 分支名称
# -D 用于强制删除,不管是否合并过
git branch -D 分支名称
分支重命名
git branch -m 旧分支名称 新分支名称
同步本地的远程分支
删除远程已经不存在但本地还存在的远程分支
git remote prune origin
git remote update origin --prune
本地分支关联远程分支
如果远程新建了一个分支,本地没有该分支,那么可以使用该命令在本地新建一个分支名叫 dev ,会自动跟踪远程的同名分支 dev
git checkout --track origin/dev
首次推送新分支到远程
git push --set-upstream origin 分支名称
tag 标签
https://git-scm.com/docs/git-tag
标签是跟 commit 挂钩的,是对某次历史提交的引用,用来给发布版本打标记
创建 tag
# 创建tag,打在最近的一次 commit 记录上
git tag v1.0.0
# 给历史版本添加tag,后接commit ID
# 这里id可以取前7位表 示,先执行 git log --pretty=oneline --abbrev-commit 可以看到
git tag v1.0.1 b3c214115924f9de069aa81d866143e52f4b5348
# 创建有备注的tag
git tag -a v1.0.0 -m '发布v1.0.0版本'
# 给历史版本创建有备注的tag
git tag -a v1.0.0 b3c214115924f9de069aa81d866143e52f4b5348 -m '历史版本带备注'
查看 tag
# 查看所有tag
git tag
# 使用通配符过滤tag
git tag -l "v1.1*"
# 查看某个tag的详细信息
git show v1.0.0
发布 tag
通常的 git push 不会将本地标签推送到远程,需要进行显式的操作
# 推送单个tag
git push origin v1.0.0
# 推送本地所有tag
git push origin --tags
删除 tag
# 删除本地tag
git tag -d v1.0.1
# 删除远程tag,有两种方式
git push origin :refs/tags/v1.0.1
git push origin --delete v1.0.1
检出标签
如果你做了某些更改然后提交它们,标签不会发生变化, 但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问,通常需要创建一个新分支
git checkout v1.0.0
# 推荐
git checkout -b new-branch v1.0.0
cherry-pick:把选中的 commits ⼀个个合并进来
cherry-pick 是⼀种特殊的合并操作,使⽤它可以点选⼀批 commits,按序合并
https://git-scm.com/docs/git-cherry-pick
关联远程仓库
1、在远程创建一个新的仓库,克隆到本地后推送
git clone git@github.com:Ivanzgh/elasticsearch.git
cd report_web
touch README.md
git add README.md
git commit -m "add README"
git push -u origin main
2、如果存在本地项目,想将其推送到 github 上,要先和远程仓库关联,然后推送
# 地址换成自己的,这里的 origin 可以自定义名称,但是一般不会更改
git remote add origin git@github.com:Ivanzgh/elasticsearch.git
git branch -M main
git push -u origin main