Git安装与配置
Git安装
安装可以参考Git官网:https://git-scm.com/
,这里不赘述
Git仓库配置
Git有三种配置方式,分别以文件的方式存储在三个不同的地方,可以使用git config
来查看不同的配置:
- 系统配置(对所有用户都适用):存放位置
/etc/gitconfig
,如果在执行git config
时带上--system
选项,那么它就会读写该文件中的配置变量; - 用户配置(只对当前用户生效):存放位置
~/.gitconfig
或~/.config/git/config
,如果在执行git config
时带上--global
选项,那么它就会读写该文件中的配置变量; - 仓库配置(只对当前项目有效):存放位置工作目录下
.git/config
,如果在执行git config
时带上--local
选项,那么它就会读写该文件中的配置变量。
优先级:仓库配置>用户配置>系统配置,即每一级别的配置会覆盖上一层的相同配置
常见Git配置
# 查看Git配置
git config -- [system/global/local]
# 配置个人身份
git config --global user.name [username]
git config --global user.email [email]
# 文本换行符配置
git config --global core.autocrlf true # 自动实现CRLF与LF转换(规避Windows换行符与Linux差异)
git config --global core.autocrlf input
# 文本编码配置
git config --global i18n.commitencoding utf-8
git config --global i18n.logoutputencoding utf-8
# 服务器认证配置
git config --global credential.helper store # 设置口令缓存
git config http.sslverify false # 添加https证书认证
远端仓库SSH认证配置
以GitHub为例,点击头像settings-->SSH and GPG keys-->New SSH key
,在本地终端生成SSH公钥 ssh-keygen -t rsa -C [key name]
,然后在本地.ssh
目录下有三个文件,其中id_rsa
是私钥文件,id_rsa.pub
是公钥文件,然后cat id_rsa.pub
查看公钥文件,将内容拷贝到GitHub的Key
中
Git四个工作区域与四种文件状态
四个工作区域
Workspace: 工作区,就是你平时存放项目代码的地方
Index / Stage: 暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息
Repository: 仓库区(或版本库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本
Remote: 远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换
git的工作流程一般是这样的:
1、在工作目录中添加、修改文件;
2、将需要进行版本管理的文件放入暂存区域;
3、将暂存区域的文件提交到git仓库。
四种文件状态
版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。Git不关心文件两个版本之间的具体差别,而是关心文件的整体是否有改变,若文件被改变,在添加提交时就生成文件新版本的快照,而判断文件整体是否改变的方法就是用SHA-1算法计算文件的校验和。
- Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过
git add
状态变为Staged
; - Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致。这种类型的文件有两种去处,如果它被修改,而变为
Modified
,如果使用git rm
移出版本库, 则成为Untracked
文件; - Modified: 文件已修改,仅仅是修改,并没有进行其他的操作。这个文件也有两个去处,通过
git add
可进入暂存staged
状态,使用git checkout
则丢弃修改过,返回到unmodify
状态,这个git checkout
即从库中取出文件,覆盖当前修改; - Staged: 暂存状态。执行
git commit
则将修改同步到库中,这时库中的文件和本地文件又变为一致,文件为Unmodify
状态。执行git reset HEAD [filename]
取消暂存,文件状态为Modified
。
四个区域常用命令
1、新建代码库
git init # 在当前目录新建一个Git代码库
git init [project-name] # 新建一个目录,将其初始化为Git代码库
git clone [url] # 下载一个项目和它的整个代码历史
2、工作区 <–> 暂存区
git add [file1] [file2] ... # 添加指定文件到暂存区
git add [dir] # 添加指定目录到暂存区,包括子目录
git add . # 添加当前目录的所有文件到暂存区
git rm [file] # 删除工作区文件,并且将这次删除放入暂存区
git rm --cached [file] # 停止追踪指定文件,但该文件会保留在工作区
git mv [file-original] [file-renamed] # 改名文件,并且将这个改名放入暂存区
git checkout [file] # 从暂存区将文件恢复到工作区,如果工作区已经有该文件,则会选择覆盖
git checkout . # 恢复暂存区的所有文件到工作区
git checkout [branch] [file] # 从指定的分支名中拉取文件并覆盖工作区里的文件
git checkout [hash-value] [file] # 恢复某个commit的指定文件到暂存区和工作区
git stash # 暂时将未提交的变化移除,稍后再移入
git stash apply # 加载上一个stash记录
git stash pop # 加载上一个stash记录,并同时删除上一个stash(git stash list中记录被删除)
3、暂存区<–>仓库区
git status # 查看文件状态
git commit -m [message] # 暂存区提交到仓库区
git commit [file1] [file2] -m [message] # 提交暂存区的指定文件到仓库区
git commit --amend -m [message] # 使用一次新的commit,替代上一次提交,如果代码没有任何新变化,则用来改写上一次commit的提交信息
git commit --amend [file1] [file2] ... # 重做上一次commit,并包括指定文件的新变化
git commit --amend -i [hash value] # 进入交互式界面,重新修改指定commit的提交记录
git reset [file] # 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
git reset --hard # 重置暂存区与工作区,与上一次commit保持一致
git reset --soft # 软撤销上一次的提交(变成add之后,commit之前状态)
git reset [hash-value] # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
git reset --hard [hash-value] # 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
git reset HEAD [file] # 撤销上次对某个文件的提交
git reset HEAD^ # 撤销上一次的提交(会直接变成add之前状态)
git reset HEAD^n # 撤销前第n次的提交
git rebase -i # 将一系列提交合并为一个提交,你可能会用它来组织混乱的提交历史记录
4、本地仓库<–>远程仓库
git remote -v # 显示所有远程仓库
git remote add [repo-name] [url] # 增加一个新的远程仓库,并命名
git clone [url] -b [branch] # 从远程仓库branch分支下载代码到本地
git push [remote] [branch] # 将本地已staged的代码推到远程别名为remote仓库的branch分支
git push [remote] [branch] -f # 强制推送
git pull [repo] [branch] # 拉取远程repo仓库branch分支的代码到本地
git fetch [remote] # 下载远程仓库的所有变动
git remote # 查看所有的仓库别名
git remote add [repo alias] [url] # 使用仓库别名替代仓库地址,如果使用了git clone命令从远程仓库获取下来的,那么这个本地仓库会自动添加一个 origin的远程地址,指向的就是克隆的远程地址
git remote remove [repo] # 删除本地存储的远端仓库别名
5、查看信息
git diff # 查看工作区与暂存区的区别
git diff --cached # 暂存区与上一个commit的区别
git diff --cached [file] # 指定文件暂存区与上一个commit的差异
git diff HEAD # 显示工作区与当前分支最新commit之间的差异
git diff [hash-value 1]...[hash-value 2] # 显示两次提交之间的差异
git log # 查看版本演进历史
git log --pretty=oneline # 在一行显示,也可以写成git log --oneline
git log --pretty=raw # 显示原始信息
git log -n # 显示最近n条commit
git log --all # 查看所有分支的提交信息
git log --graph # 以图的形式展示
git show [commit]:[filename] # 显示某次提交时,某个文件的内容
git reflog # 显示当前分支的最近几次提交
gitk --all # 以可视化界面的形式展示git历史
6、gitk:git图形化操作工具
gitk --all
Git Tag
git tag # 列出所有tag
git show [tag] # 查看tag信息
git tag [tag] # 新建一个tag在当前commit
git tag [tag] [commit] # 新建一个tag在指定commit
git tag -d [tag] # 删除本地tag
git push origin :refs/tags/[tagName] # 删除远程tag
git push [remote] [tag] # 提交指定tag
git push [remote] --tags # 提交所有tag
git checkout -b [branch] [tag] # 新建一个分支,指向某个tag
Git分支
分支的查看、创建、删除 、合并
查看当前有哪些分支
git branch # 查看本地分支
git branch -r # 列出所有远程分支
git branch -a # 查看所有分支(本地+远程)
创建一个新的分支
git branch [branch] # 创建一个新的分支
git checkout -b [branch] # 创建一个新的分支并切换到新的分支
git checkout -b [branch] [hash-value] # 新建并切换一个分支,指向指定commit
git branch --track [branch] [remote-branch] # 新建一个分支,与指定的远程分支建立追踪关系
git branch --set-upstream [branch] [remote-branch] # 建立追踪关系,在现有分支与指定的远程分支之间
分支切换
git checkout [branch] # 切换到指定分支,并更新工作区
删除分支
git branch -d [branch] # 删除本地分支
git branch -D [branch] # 强制删除本地分支
git push origin --delete [branch] # 删除远程分支
分支合并
git merge [branch] # 将<branch>分支合并到当前分支
git cherry-pick [commit] # 选择一个commit,合并进当前分支
分支合并分为三种情况:
-
快进合并(fast-forward)
-
三方合并(three way)
-
git rebase变基合并
合并冲突解决方法
- git status 查看存在哪些冲突
- 解决冲突
- git add [file],提交解决冲突后的代码
Git内部原理
初探.git目录
$ tree ./git
├── HEAD
├── config
├── description
├── hooks
│ ├── xxx.sample
│ ...
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ ├── heads
│ │ └── main
│ └── remotes
│ └── origin
│ └── HEAD
├── objects
│ ├── info
│ └── pack
│ ├── pack-3dd3f5b1a24a15b34e24f8fcf1f83f1511c48a2d.idx
│ └── pack-3dd3f5b1a24a15b34e24f8fcf1f83f1511c48a2d.pack
├── packed-refs
└── refs
├── heads
│ └── main
├── remotes
│ └── origin
│ └── HEAD
└── tags
这里介绍四个很重要的条目:HEAD
文件、index文件、
objects 目录、
refs目录。 它们都是 Git 的核心组成部分。
objects 目录存储所有数据内容;
refs目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针;
HEAD 文件指向目前被checkout的分支;
index` 文件保存暂存区信息。
objects目录:Git 对象
git对象(commit,tree,blob)之间的关系
一个分支对应多个commit,其中tree是文件夹对象,对应多个blog对象,blob是文件对象
refs目录
ref(引用)存放的是一个SHA-1的散列值,指向Git对象库中的对象。本地特性分支名称、远程跟踪分支名称和标签名都是引用。
Git引用:人类取的别名指向一个Git对象
refs/heads/red # 代表本地分支
refs/remotes/red # 代表远程跟踪分支
refs/tags/red # 代表标签
refs目录存储所有的分支,每个分支存储的是当前分支最新的提交的commit对象
$ cat .git/refs
.git/refs
├── heads
│ └── main # 35551f9a0f66a22de4971b4a51b3c172d3b87f95
├── remotes
│ └── origin
│ └── HEAD # ref: refs/remotes/origin/main
└── tags
头指针HEAD
指向当前分支最新的提交commit
$ cat .git/HEAD
ref: refs/heads/main
分离头指针(detached HEAD)
HEAD指向的commit id
在没有任何分支上,可以在分离头指针上先做实验性的功能,当验证成功后在checkout到对应分支上面。
深入理解HEAD和分支以及tree-ish表达式
git rev-parse HEAD # 解析当前分支最新的提交commit id
git rev-parse HEAD~ # 解析当前分支上一个提交commit id
git rev-parse HEAD~n # n表示前n个commit
git cat-file <commit id> 查看commit的详细信息
git cat-file -p <>
git cat-file -t 查看hash对象
git cat-file <obj_name>\<hash value> 查看对象的内容
当obj是commit对象,展示的是。。。。。
当obj是tree对象,展示的是指向blob的hash。git ls-tree \<hash value>
当obj是blob对象,展示的是文件内容
git常见问题及解决办法
如何修改最近的commit message
git commit --amend
然后利用vi编辑器编辑修改commit message
当需要修改已提交的用户名和邮箱信息时,也可以通过以下命令快捷修改
git commit --amend --author "cxiaolong <2845907121@qq.com>" --no-edit
如何修改以前的commit message
git rebase -i [parent commit id]
然后可以根据提示在vi编辑器修改在之前的commit上增加r
或者reward
,之后在交互式界面修改历史commit信息
如何将连续或间隔的几个commit整理成一个commit
git rebase -i [parent commit id]
然后使用vi编辑器在对应commit前将pick修改为s(squash)
,即可实现几个commit的合并
如何比较暂存区和HEAD的文件差异
git diff --cached
如何比较工作区和暂存区的文件差异
git diff
git diff [file] # 查看指定文件的差异
如何查看不同commit的差异
git diff [commit_id 1] [ommit_id 2]
git diff [commit_id 1] [ommit_id 2] --[file] # 查看指定文件的差异
如何让暂存区的文件恢复到与HEAD一样
git reset HEAD
git reset HEAD [file]
git reset [file1] [file2]
如何让工作区的文件恢复到跟暂存区一样
git checkout [file]
如何使用git stash帮助我们处理临时任务
git stash # 保存一个临时的状态
git stash apply # 加载上一个stash记录
git stash pop # 加载上一个stash记录,并同时删除上一个stash(git stash list中记录被删除)
如何指定git不需要管理的文件
在.gitignore
文件中写入不需要管理的文件
Reference
[1]: https://git-scm.com/book/zh/v2/
[2]: https://gitee.com/all-about-git
[3]: https://dev.to/lydiahallie/cs-visualized-useful-git-commands-37p1
[4]: https://zhuanlan.zhihu.com/p/584182115