四区

1.工作区
也就是自己本地的工作目录,其中含有.git隐藏文件,其内部包含git使用的各种数据文件,最好不要动它。
2.暂存区
一般存放在.git目录下的index 文件(.git/index)中,我们把暂存区有时也叫作索引(index)
字面意思也就是一个中间存储区,可以将多个修改文件先都放在暂存区,然后一并上传至本地仓库。就像是打包发送一样。
3.本地仓库
用来存放全部的数据仓库,也就是管理的仓库。
它就是.git这个文件,包含着许多操作信息等。
4.远程仓库
一个在远端的仓库,可以是在gitee或者github上的一个仓库。看作是一个"中央服务器"仓库,通过与本地仓库进行关联,来达到工程项目的版本管理。
Git用户配置
安装Git之后首先要做的就是要设置自己的用户名和邮箱,要与远程仓库的用户信息一致。
git config [--global] user.name "Your Name"
Your Name替换成自己的用户名
git config [--global] user.email "email@example.com"
其中邮箱填写相应的个人邮箱
其中--global选项表示在全局范围生效,以后在其他地方的本地仓库用的也会是这个配置信息。
可以使用
git config -l命令来查看配置信息
删除对应的配置信息:
git config [--global] --unset user.name
git config [--global] --unset user.email
创建远程仓库并配置公钥
一般来讲,既然要用git管理,首先肯定要有一个远程仓库。
可以在gitee和github上自己创建一个,然后用ssh的方式来连接远程的仓库。
- 首先要看自己有没有配置ssh公钥:
在此用户的家目录~下看有没有.ssh文件,有的话再看.ssh里有没有id_xxx和id**_**xxx.hub这两个文件,有这两个文件说明已经配置了公钥;
-
如果没有这两个文件就在终端上输入
ssh-keygen -t ed25519 -C "你的邮箱@example.com"
然后一直按回车默认设置就行,会提示设置一个密码短语passphrase,确认后公钥就生成好了。
-
然后再输入
cat ~/.ssh/id_ed25519.pub
显示公钥后全部复制,登录gitee或github,点击头像,进入setting,找到ssh,然后添加就行了。
-
之后可以在终端中测试有没有成功
ssh -T git@github.com
若显示:Hi 你的用户名! You've successfully authenticated, but GitHub does not provide shell access.
说明配置成功了。
本地仓库init创建
在要管理的目录路径下输入命令:
git init
那么此时此目录下会多一个.git隐藏文件,那么本地仓库就创建好了
三区交互
工作区->暂存区
工作区的任何改动:对文本的修改,对文件的删除、增加以及任何其他对此工作目录的操作都算是改动。无论是一次还是多次改动,都可以通过git add .命令对所有改动一键上传至暂存区。
例如:
添加一个文件test.txt不git add .时,使用命令git status查看仓库状态,能看到改动提示:
$ git status On branch main Your branch is up to date with 'origin/main'.
Untracked files: (use "git add <file>..." to include in what will be committed) test.txt
nothing added to commit but untracked files present (use "git add" to track)
所以需要git add .来添加进暂存区
添加之后再git status会出现:

此时所有改动(这里指添加的test.txt文件)就上传至暂存库里面了
对比工作区与暂存区的改动
通过命令git diff来查看工作区与暂存区的变化。注意:只有已经git add过的文件才会被追踪,没有被追踪的文件git diff之后不会显示变化。
例如:
在test.txt文件中写入hello之后再git diff

那么此时再看一下状态:git status

所以此时就还需要git add .上传至暂存区了。

暂存区->本地仓库
使用命令git commit -m "本次提交的提示内容"
选项-m表示增加提示,必须要带!!!增加管理的便捷。
如果提示写错了,可以通过命令git commit --amend -m "新提示"。
commit默认是将暂存区所有改动都上传至本地仓库,如果想部分上传,就在commit后面加上对应要上传的文件名
接续上文:已经add了文件test.txt。
此时需要git commit -m '...'

那么commit之后我们可以使用命令git log来查看提交记录:

那么为了更加直观的查看log,我们可以配置git log命令:
图形精简日志(替代 git log --oneline --graph --decorate)
git config --global alias.lg "log --oneline --graph --decorate"
-
git config:配置 Git -
--global:全局生效(所有仓库都能用这个别名) -
alias.lg:定义一个别名,名字叫 lg -
后面双引号里的内容:别名真正执行的命令
-
--oneline:把每一条提交记录压缩成一行 ,只显示:短哈希 + 提交信息 -
--graph:用 ASCII 图形 显示分支、合并结构 -
--decorate:显示标签(tag) 和分支名(branch)
版本回退
本质是回退本地仓库 的的版本,对于工作区 和暂存区的内容回退要通过添加参数来进行。(回退HEAD指针)
命令:git reset [--soft | --mixed | --hard] [HEADID]
[HEADID]:指的是commit提交ID原本有40位,但是一般用前7位就行了。
[HEAD~]默认是是上一次提交,后面跟数字几的话就是回退到上几次提交。

例如:
回到上一次提交:git reset HEAD~

此时暂存区 和本地仓库都没有文件test.txt了。
那么我们还可以使用命令git reflog来查看版本指针变动记录
git reflog:记录本地 HEAD 指针的所有移动记录 :只要 HEAD 动了就会记,包括 checkout切换分支、reset回退版本、commit提交、merge合并 等所有操作 。只保存在本地,不会推到远程仓库。

撤销工作区修改
命令git checkout -- .
将当前工作区的所有修改都回退到上一次add到暂存区时的状态。也就是只对工作区进行回退。
注意:本没有add的文件没有被跟踪,checkout会失效,但是我们新加的文件要回退到上一次add暂存区的状态不也就是没有这个文件吗?直接删除就行了。

例如:
将文件test.txt里的内容从hello world改成了hello但是没add,想要回到hello world

要撤回这次在工作区的改动:git checkout -- .

删除文件
删除文件其实也就是在工作区的改变嘛。用rm->git add->git commit就能将三区的文件删除
但如果用git里的rm的话可以直接对工作区 和暂存区 的两个区域同时删掉,最后只要我们自己git commit -m ''就行了
命令:git rm [文件名]
分支
-
分支就是指针,指向一条提交commit链
-
创建分支就是复制指针 ,切换分支就是移动HEAD
-
HEAD指向的就是当前工作的分支
1.查看分支
git branch命令

2.添加分支
-
只添加分支,不移动HEAD:
git branch [新分支名] -
添加分支,并将HEAD移动至新分支上:
git checkout -b [新分支名]
3.移动HEAD
移动HEAD就是将当前的工作分支切换
命令:git checkout [分支名]
当移动HEAD切换分支时,不同分支的数据很可能已经不一样了,也就是说你到新的分支之后,原本本地仓库里有的文件可能会不见。

4.分支合并
命令:git merge [分支名],将目标分支合并到当前(也就是HEAD指向的)分支上。
有三种情况:
- 快速合并
目标分支dev已经commit了好几次,而main分支没动,我要将dev合并到main分支上,此时就是Fast forword快速合并。
发生快速合并时,相当于HEAD->main指针直接跳到了dev上,那之后去看那些commit提交就不知道是谁提交的了。
在团队协作中禁止快速合并,所以这时要在命令里加参数:--no-ff。合并时会跳出来让你填写以下新commit的提示,这里的commit不是你手动的,而是在合并时自动创建的新commit,表示通过--no-ff的合并。


- 交叉合并
main分支和dev分支都有各自的commit,需要两者都合并在一起

- 冲突合并
当main和dev修改了同一行的代码,合并时会报错。
例如当我在main分支在test.txt文件最后加上A;在dev分支在test.txt文件最后加上a,再合并。
此时在test.txt文件报错

打开test.txt文件查看:

<<<<<<< HEAD // 下面是【当前main分支】的代码 A //main改的内容 ======= // 分割线:上面是main的,下面是dev的 a //dev改的内容 >>>>>>> dev // 下面是【要合并的dev分支】的代码
解决步骤:
1.手动改文件(3 选 1)
打开冲突文件,删掉标记,保留最终代码:
-
只留自己的:删掉别人的代码 + 所有标记
-
只留别人的:删掉自己的代码 + 所有标记
-
两个都要:手动整合代码,删掉所有标记
2.解决完必须执行两步
# 1. 把解决完的文件加入暂存区
git add .
# 2. 手动生成合并提交(Git不会自动commit)
git commit -m "解决dev和main的合并冲突"

5.删除分支
-
不能在当前分支删自己,首先要切出要删除的分支;
-
安全删除:
git branch -d [分支名],会校验分支是否已合并到当前分支,未合并则禁止删除(防丢代码); -
强制删除:
git branch -D [分支名],分支有未合并提交、确定不需要了才用; -
检查分支:
git branch,查看是否删除成功。
commit的提交是一条一条串起来的链,分支名只是一个指向某个提交的标签(指针),不是代码本身。
删分支 = 删掉这个标签,不是删掉提交本身。所以提交记录还会存在。
分支存在的意义:协作、流转、临时功能。一旦使命结束,立刻删掉,留着只会分支泛滥、log 混乱、合并风险变高。
6.bug分支策略
当你还在dev分支上开发时,main分支突然出了bug,那么此时你需要保存你在dev上的开发,去到main分支上开一个bugfix分支,进行bug修改。
使用命令:
git stash push -m "备注:临时保存XX功能";
git stash list查看stash列表


stash过的记录就像是一个临时的commit。
再合并bugfix分支:


再回到dev分支,恢复stash的留存:
git checkout dev
git stash pop:恢复并删除 stash
注意:
-
stash 只存:已跟踪文件的修改;不存:新建未跟踪文件、.gitignore 忽略的文件;
-
stash 是全局的,所有分支共享,在哪都能取
其他
-
git stash apply stash@{0}:恢复并保留 stash,还能在stash列表里看见留存; -
git stash drop stash@{0}:删除指定stash; -
git stash clear:清空所有stash。
恢复stash后如果要将dev开发好的合并至main,此时的dev很可能与main冲突,如果直接合并至main上,会导致main分支异常:

所以我们不采用以上这种合并方法
我们通过将main分支合并拉取到dev分支上,在dev分支上解决冲突;

解决冲突后,再在main分支上,合并dev分支,一般来说就不会有冲突

最后
我们思考,dev分支通过stash留存数据,跟一个临时commit差不多,那为什么我们不直接commit一个新的节点,修完bug之后直接到这个commit这继续开发呢?当然不行。
stash 是「临时藏一下,不留痕迹」,commit 是「硬写进历史,删不掉」
如果真的用commit去储藏dev,会污染dev分支的历史。
远程仓库
远程仓库关联
- 本地初始化后再关联
如果在本地目录通过init初始化一个git仓库,默认是没有关联远程仓库的,我们要通过命令关联:
git remote add origin [远程仓库地址],
origin 不是关键字、不是固定单词,就是给远程仓库起的一个别名(昵称) ,默认都习惯叫 origin.
一个本地仓库可以关联多个远程仓库,所以给不同的远程仓库取别名就很方便。
例如:我创建一个新的目录testRemote初始化git仓库,再关联远程仓库

默认的本地主分支叫master。
- 直接到从远程仓库复制仓库地址克隆到本地(配置好公钥)
首先去远程仓库那复制地址:git@github.com:zincsweet/test_new.git
到一个新建文件夹中打开git bash输入命令:
git clone [仓库网络地址]:会在此文件夹下新建一个以远程仓库命名的文件夹,也就是已经关联的本地仓库。
默认的主分支叫main。

本地推送至远程
只是将当前本地仓库HEAD所在的分支推送,不能推送全部
命令:git push,这是已经绑定远程和本地的分支的情况下,直接push会推送到对应的关联分支上。下面会讲述如何关联远程分支。
远程分支绑定
远程仓库有分支,本地也有分支,对应分支上的开发肯定要同步跟踪,而且远程与本地的分支要一一对应。一个本地分支只能绑定一个远程分支。
绑定分支之后能将本地分支与远程分支联系起来,以后git push也不用每次后面都加origin main,直接写git push就行。
绑定分支有两种方式:
- 在第一次分支推送时一键关联
git push -u origin [远程分支名]

可以通过命令:git branch -vv来查看分支管理
-u就是--set-upstream的缩写,意思是设置上游分支。

有[origin/dev]说明已经绑定好远程分支了,像bugfix就是还没绑定远程;
在[origin/main: ahead 13]说明本地main分支有13次commit没有推送至远程。
- 不push,直接绑定一个分支
git branch --set-upstream-to=origin/bugfix bugfix,这时,远程必须要已经有一个分支bugfix,不然会报错:

所以这里用上面的push -u的方式,不要忘记先要checkout切换到bugfix分支:

- 取消当前分支绑定
git branch --unset-upstream
分支拉取
当远程仓库有的分支比本地分支开发得快,想要把远端分支的数据更新到本地仓库可以用:
git fetch [远程仓库别名] [指定分支]:若不加后两个参数就默认拉取全部远程仓库的更新,只下载过来,不直接合并,安全,可以先看再合并;
git pull [远程仓库别名] [指定分支]:若不加后两个参数 ,表示只拉取当前分支对应远程分支代码合并,直接合并。相当于fetch+merge。
(为了不在合并时快速合并ff,配置:git config --global merge.ff false、git config --global pull.ff false)
配置.gitignore
.gitignore 是 Git 的忽略配置文件,写在里面的文件 / 文件夹名,Git 永远不追踪、不提交、不纳入版本管理。
必须放在仓库根目录,和 .git 同级。
# 忽略单个文件 a.txt config.ini # 忽略整个文件夹 node_modules/ dist/ build/ # 忽略所有后缀 .log 的文件 *.log # 忽略某目录下所有文件 temp/* # 不忽略(例外) # 忽略所有 js,但保留 index.js *.js !index.js
常用的模板:
# 依赖 node_modules/ venv/ env/ # 编译输出 dist/ build/ out/ # 日志 *.log # 系统垃圾 .DS_Store Thumbs.db # 编辑器配置 .vscode/ .idea/ *.swp *.swo
注意:
-
文件已经被 Git 追踪了,写进 ignore 没用,.gitignore 只管还没被 add 的文件;
-
结尾加
/代表是文件夹
# 只忽略叫 logs 的文件夹 logs/ # 忽略所有叫 logs 的文件 + 文件夹 logs
配置Git命令别名
语法:
# 全局(所有仓库生效,推荐) git config --global alias.别名 "原命令" # 本地(仅当前仓库生效) git config alias.别名 "原命令"
例如:
# 好看的日志 git config --global alias.lg=log --oneline --graph --decorate
标签管理
标签(Tag)就是给某一次代码提交,起一个固定的版本记号。
一、创建标签
git tag -a v0.9.0 提交哈希值 -m "版本标签备注"
-
v0.9.0:标签名; -
[提交哈希值]:若不填,默认就是当前分支的最新一次提交。
二、查看标签

# 列出所有标签 git tag # 查看标签详情(有备注的标签才有用) git show v1.0.0
三、推送标签
# 推送单个标签 git push origin v1.0.0 # 推送所有本地标签 git push origin --tags


四、删除标签
# 1. 删除本地标签 git tag -d v1.0.0 # 2. 删除远程标签 git push origin --delete tag v1.0.0
注意区分:
# 删远程分支 git push origin --delete 分支名 # 删远程标签 git push origin --delete tag 标签名
