创建仓库
# 创建本地仓库到当前文件夹
git init
# 创建本地仓库到当前文件夹下的子文件夹
git init <子文件夹>
# 拉取远程已存在的仓库到本地(使用远程仓库名)
git clone <远程仓库地址>
# 拉取远程已存在的仓库到本地(使用新名字)
git clone <远程仓库地址> <新名字>
工作区域和文件状态
工作区域:
- 工作区(Working Directory):
.git
所在的目录 - 暂存区(Staging Area / Index):
.git/index
- 本地仓库(Local Repository):
.git/objects
文件状态:
- 未跟踪(Untrack):新建的文件,没有被 git 管理
- 未修改(Unmodified):被 git 管理的文件,没有在工作区进行修改
- 已修改(Modified):被 git 管理的文件,在工作区进行了修改
- 已暂存(Staged):已添加到暂存区
命令:
git status
:查看仓库状态git add
:添加到暂存区git commit
:提交到本地仓库git log
:查看仓库提交历史记录--oneline
:每条历史记录显示一行
git reset
回退到某个版本,版本是指提交到本地仓库的记录
git reset --soft
:回退到某一版本,保留到工作区和暂存区git reset --hard
:回退到某一版本,丢弃工作区和暂存区git reset --mixed
(默认):回退到某一版本,保留工作区,丢弃暂存区
soft
和 mixed
基本相似,使用场景是连续提交了多个没有意义的版本,可以回退,合并成一个版本重新提交
hard
的使用场景是真的要放弃某个版本之后的所有提交
git reflog
查看操作记录,使用 git reset --hard
回退到某个操作
git diff
查看三个工作区域之间的差异、不同版本之间的差异、不同分支之间的差异
git diff
:查看工作区和暂存区之间的差异git diff HEAD
:查看工作区+暂存区和版本库(本地仓库)之间的差异git diff --staged
或git diff --cached
:查看暂存区和版本库之间的差异git diff <commitHash 1> <commitHash 2>
:查看不同版本之间的差异git diff <branchName 1> <branchName 2>
:查看不同分支之间的差异
在命令后面还可以写一个或多个文件名,表示只看某些文件的差异
HEAD
:
HEAD
:表示当前的所在的提交节点,默认指向当前分支的最新提交节点HEAD^
或HEAD~
:HEAD
的前一个提交HEAD^<n>
或HEAD~<n>
:HEAD
的前 n 个提交
git rm
rm <file>; git add <file>
:先从工作区删除文件,再将删除操作添加到暂存区git rm <file>
:把文件从工作区和暂存区同时删除git rm --cached <file>
:把文件从 暂存区删除,但保留在工作区中git rm -r *
:递归删除某个目录下的所有子目录和文件(从工作区和暂存区同时删除)
注意:以上都只是在工作区和暂存区进行操作,记得提交到版本库
.gitignore
应该忽略的文件:
- 系统或应用自动生成的文件
- 编译产生的中间文件和结果文件
- 运行时生成的日志文件、缓存文件、临时文件
- 涉及身份、密码、口令、密钥等敏感信息的文件
- 依赖库,如:
node_modules
.gitignore
文件匹配规则:
- 从上到下逐行匹配,每一行表示一个忽略模式
- 空行或以
#
开头的行会被忽略- 空行用于可读性的分割
#
表示注释
- 使用标准的 glob 模式匹配,例如:
*
通配任意个字符?
匹配单个字符[]
表示匹配列表中的单个字符,如:[abc]
表示 a 或 b 或 c[]
中可以使用短中线连接,如:[1-9]
表示 1~9 之间的任意一个数字**
表示匹配任意的中间目录/
结尾表示目录!
表示取反
注意:
- git 不会管理空文件夹,解决方法是在空文件夹下新建一个
.gitkeep
空文件即可 - 在
.gitignore
忽略之前就提交到版本库中的文件不受.gitignore
控制,可以使用git rm --cached <file>
将其从版本库中删除
远程仓库
- HTTPS 协议:写操作需要验证 github 用户名和密码
- 2021 年 8 月 13 日以后,github 停止用户名和密码的验证方式
- 可以用 token 或 web auth 验证
- SSH 协议:写操作不需要用户名和密码,但需要在 github 上添加 SSH 公钥的配置(推荐:更加安全和方便)
# 进入家目录的 .ssh 目录
cd ~/.ssh
# 生成 SSH 密钥对
# -t rsa:指定使用 rsa 协议
#-b 4096:指定生成的大小为 4096
ssh-keygen -t rsa -b 4096
# 过程需要输入文件名称,直接回车则默认生成名称为 id_rsa
# 会生成两个密钥文件
id_rsa # 私钥
id_rsa.pub # 公钥
如果不使用默认名称 id_rsa
,则需要在 ~/.ssh
文件夹下创建一个 config
文件,指定 github 使用的密钥:
# github
Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/test
git remote add <远程仓库别名> <远程仓库地址>
:添加远程仓库(本地仓库与远程仓库关联)git remote -v
:添加本地仓库所关联的远程仓库git branch -M <newName>
:将当前分支重命名git push -u <远程仓库别名> <本地分支名>:<远程分支名>
:将本地分支内容 推送到远程,并关联分支- 当本地分支名与远程分支名同名时,可以简写
<远程分支名>:<本地分支名>
为分支名
- 当本地分支名与远程分支名同名时,可以简写
git pull <远程仓库别名> <远程分支名>:<本地分支名>
:拉取远程仓库内容到本地- 当本地分支名与远程分支名同名时,可以简写
<远程分支名>:<本地分支名>
为分支名
- 一般直接写
git pull
表示拉取默认关联的远程仓库的关联分支
- 当本地分支名与远程分支名同名时,可以简写
分支
git branch
:查看所有本地分支(前面带有*
的是当前所在分支)git branch <新分支名>
:基于当前HEAD
创建一个新分支(不会切换到新分支,而是还在HEAD
)git switch <分支名>
:切换分支git switch -
:切换到上一个分支
git checkout <分支名>
:- 切换分支
- 恢复文件
- 移动
HEAD
git merge <将要被合并的分支>
:把将要合并的分支合并到当前分支- 删除本地分支:
git branch -d <分支名>
:删除已合并的本地分支git branch -D <分支名>
:强制删除本地分支,无论是否已合并- 注意:不能在将要删除的分支执行以上命令(不能把自己举起来)
合并冲突
- 两个分支没有修改同一个文件的同一处位置:Git 自动合并
- 两个分支修改了同一个文件的同一处位置:产生冲突
解决方法:
- 手动修改冲突文件的内容
- 添加到暂存区
- 提交到本地仓库
中止合并:git merge --abort
变基
除了 merge
合并分支外,还有一种方法将多个分支整合到一起,那就是:rebase
变基
git rebase <将要变基到的分支>
:将当前分支的新提交变基到目标分支
流程:
- 找到两个分支的公共祖先
- 将当前分支的新提交变基到目标分支
- merge
- 优点:不会破坏原分支的提交记录,方便回溯和查看
- 缺点:会产生额外的提交节点;分支图比较复杂
- rebase
- 优点:不会新增额外的提交记录;形成线性历史,非常直观和干净
- 缺点:会改变提交历史,改变了当前分支 branch out 的节点