git 版本: 2.40.1.windows.1
文章目录
- 一. 使用git之前你必须要理解的几个概念
- 1.1 理解工作区、版本库、暂存区的概念
- 1.2 提交Git版本库的步骤【分两步执行】
- 二. Git本地库实战
- 2.1 初始化版本库
- 2.2 新建 & 提交 & 状态
- 2.3 查看日志
- 2.4 回退 & 穿梭 & 撤销
- 2.4.1 回退到历史版本
- 2.4.2 版本穿梭
- 2.4.3 撤销文件
- 2.5 删除
- 2.6 分支
- 2.6.1 实际开发流程
- 2.6.2 分支概念
- 2.6.3. 分支的好处
- 2.6.4 分支操作
- 2.6.5 分支操作详解
- 1) 创建分支和切换分支之图解
- 2) 如何创建分支和切换分支?
- 3)如何删除分支?
- 4) 如何合并分支?
- 2.7 git追踪的文件数据丢失了,怎么办?
- 1.问题描述
- 2.问题原因
- 3.解决方案
- 2.8 版本冲突
- 1. 冲突产生的表现
- 2. 冲突产生的原因
- 3. 冲突的解决
- 4. 避免冲突
一. 使用git之前你必须要理解的几个概念
1.1 理解工作区、版本库、暂存区的概念
以本人电脑桌面上的文件夹git_test举例说明
-
工作区(Working Directory)
:就是电脑本地的硬盘目录 -
版本库(Repository)
:工作区有个隐藏目录 .git ,它就是Git的本地版本库
-
暂存区(stage)
:一般存放在"git目录"下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index) -
分支(Branch)
:Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD
1.2 提交Git版本库的步骤【分两步执行】
👉第一步
用“git add”把文件纳入Git管理,实际是把本地文件修改添加到暂存区
👉第二步
用“git commit”提交更改,实际上就是把暂存区的所有内容提交到当前分支
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以commit就是往master分支上提交更改。
可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。一旦提交完后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的。即:nothing to commit (working directory clean)。
👉其他操作
①用“git diff HEAD – filename”命令可以查看工作区和暂存区里面最新版本的区别。
②撤销未add的文件: git checkout --文件名
③撤销已add未commit的文件:先git reset [HEAD] 文件名,再 git checkout – 文件名
④撤销已add已commit:git reset --hard HEAD^ 【^ -> 回退一个版本,^^ -> 回退两个版本,剩下依此类推,如果嫌麻烦,想回退多个版本,后面加~+数字
二. Git本地库实战
👉 常用命令预览
命令名称 | 命令作用 |
---|---|
git init | 初始化本地库,生成.git 目录【本地库】 |
git config --global user.name 用户名 | 设置用户签名的用户名部分 |
git config --global user.email 邮箱 | 设置用户签名的邮箱部分 |
git status | 查看本地库状态 |
git add 文件名 | 添加到暂存区 |
git commit -m “日志信息” 文件名 | 提交到本地库 |
git reflog | 查看历史记录 |
git reset --hard 版本号 | 版本穿梭 |
2.1 初始化版本库
👉前提
要使用Git对我们的代码进行版本控制,首先需要获得Git仓库
👉获取Git仓库通常有两种方式
- 在本地初始化一个Git仓库
- 从远程仓库克隆
❓如何在本地初始化一个Git仓库?
①创建目录(用作本地版本库),例如:C:\Users\king\Desktop\git_test,git_test表示你自己新建的项目名称
②当前目录打开Git Bash窗口,初始化仓库
👉初始化仓库命令
git init
💡注意
我这里git报了一个“ Reinitialized existing Git repository in
C:/Users/king/Desktop/git_test/.git/ ”的提示信息。
它表示在路径 “C:/Users/king/Desktop/git_test/” 下重新初始化了一个已存在的 Git 仓库。
🤔原先存在的git仓库数据会被清空吗?
是的,执行
git init
命令时,如果指定的路径下已经存在一个 Git 仓库,并且重新初始化了该仓库,那么原有的 Git仓库数据将被清除。这意味着之前的提交历史、分支、标签等所有与该仓库相关的数据都将被删除。 在重新初始化后,该仓库会变成一个空的、新的 Git 仓库,需要重新添加文件、进行提交等操作,因此建议对重要项目的git仓库做好备份
💡ps:我这里所说的git仓库就是上文介绍的git本地版本库
③查看当前目录产生 .git隐藏文件夹
💡注意:当前的 .git 是一个隐藏文件夹,需要在电脑上面设置隐藏文件夹显示设置,否则,看不到这个.git目录,可参考如下步骤查看隐藏文件夹
2.2 新建 & 提交 & 状态
1.新建文件
👉命令
-
touch a.txt:新建一个空白文件
-
vim a.txt:编辑文件
2.查看文件状态
👉命令
git status
- On branch master :表示主分支
- Untracked files:表示未跟踪状态
👉Git工作目录下的文件状态信息如下
Untracked
:未跟踪(未被纳入版本控制)Tracked
:已跟踪(被纳入版本控制)Unmodified
:未修改状态Modified
:已修改状态Staged
:已暂存状态
💡注意这些文件的状态会随着我们执行Git的命令而发生变化
红色
:表示新建文件或者新修改的文件,都在工作区绿色
:表示文件在暂存区- 一般新建的文件存放在工作区,它需要被添加到暂存区并提交到本地库中
👉也可以使用git status –s 使输出信息更加简洁
-
??
: 表示未跟踪状态
3.添加到暂存区
👉命令
git add <文件名称>
:只是增加到栈空间(index文件)中,还没有添加到本地库中。初始化时没有这个index文件。这还是一个新文件,需要将栈空间文件提交到本地仓库- git add:添加项目中所有文件
👉举例演示
将刚创建的文件[a.txt]添加到缓存区中
💡注意
①添加未存在文件会出错,错误信息为【fatal: pathspec ‘hello.txt’ did not match any files】
🤔不信?请看如下案例
使用命令 git add hello.txt 添加不存在的文件[hello.txt]到缓存区中
②使用git add 文件名时,可以使用Tab键自动补全其文件名
4.撤销暂存区的文件
👉命令
git reset <文件名称>
:撤销后,查看文件状态(git status)文件由绿色变为红色
👉举例演示
将添加到缓存区中的文件[a.txt]撤销,使其回到工作区中
5.将暂存区文件提交到本地库
👉命令
-
git commit
:执该行命令时需手动填写提交日志[备注/注释],进入编辑模式不信?请看如下演示
-
git commit –m “注释内容”
:直接用-m参数指定日志内容,推荐,因为commit 会生成一条版本记录,add只是添加暂存区,不会生成版本记录,建议多次add后,一次性commit,避免每次add都commit产生版本信息爆炸 -
git commit -am "注释内容"
:代码编辑完成后即可进行 add 和 commit 操作,此命令是添加和提交的合并命令
👉举例演示
将文件[a.txt]提交到本地库中
💡注意
虽然git commit -am "注释内容"
命令虽然可以**将已跟踪的修改直接添加到暂存区,并创建一个新的提交记录,将这些修改永久保存到版本库中
,但是该命令只适用于对已经添加到版本库中的文件进行修改,且修改后的文件需要被提交
, 换而言之,不能对工作区中的文件一键添加并提交到本地库中。对于新添加的未跟踪文件,仍然需要先使用 git add
命令将其添加到暂存区,然后再使用 git commit -m "注释内容"
进行提交。
2.3 查看日志
👉命令
-
git log
:显示提交日志信息 -
git log a.txt
:文件日志(查看所有日志或某个文件日志),按q退出
-
git log --pretty=oneline
:如果日志很多,可以在一行显示 -
git reflog
:查看所有的历史操作
2.4 回退 & 穿梭 & 撤销
2.4.1 回退到历史版本
👉命令
-
git reset --hard HEAD\^
:一次回退一个版本,一个^代表一个版本数量 -
git reset --hard HEAD~n
:回退n次操作
👉举例演示:
对b.txt文件回退到上一个版本
执行回退命令前
执行回退命令后
2.4.2 版本穿梭
👉步骤
git reflog 文件名
:查看指定文件的历史操作git reset --hard 版本号
:回到指定的版本
👉举例演示:
文件b.txt已经插入了三条数据,且每次插入数据后都提交到了本地库中,现需要将b.txt文件穿梭到第一版[即插入“第一次插入数据”的b.txt]
执行版本穿梭命令前
执行版本穿梭命令后
2.4.3 撤销文件
🚩情形1(未add,未commit的文件)
👉命令
git checkout -- 文件名
:撤销修改,即还原原来的文件
👉理解
该命令的主要作用是将指定文件恢复到最近一次提交的状态。简而言之,如果你在工作区对某个文件做了修改,但是还没有使用 git add
将其添加到暂存区,那么可以使用 git checkout -- <文件名>
命令来撤销对文件的修改,将其恢复为最近一次提交的状态。这里有个使用前提,如果你的文件仅仅只是在工作区中新增并修改了一个文件,比如c.txt,再使用 git checkout -- c.txt
命令撤销文件,会报错,报错信息如下所示:
🤔why?
我在工作区中新建并修改了文件C.txt,该文件没有被add,即添加进缓存区中,Git 在执行撤销操作时,会检查文件是否已经被 Git 跟踪(即已添加到 Git 中)。由于 ‘c.txt’ 文件尚未被添加到 Git 中,因此 Git 不知道如何撤销该文件的更改。 故会报错,该命令的使用场景是你在工作区新增并修改了某个文件,把文件add到缓存区,紧接着你第二次修改了这个文件,但没有add到缓存区,就可以使用该命令撤销第二次修改的数据,恢复到第一次修改时的状态。
🤔 如何得知某个文件是否已经被 Git 跟踪?
要想确定文件是否已经被 Git 跟踪,可以使用 git status
命令来查看文件的状态。
在终端或命令行界面中,进入到该文件所在的工作目录,并运行 git status
命令。Git 将显示当前分支的状态以及与之相关的文件信息。
如果文件已经被 Git 跟踪,git status
命令的输出中会显示在 “Changes to be committed
” 或者 “Changes not staged for commit
” 部分下列出该文件。
如果文件没有被 Git 跟踪,则不会在上述两个部分中显示该文件,而是会出现在 “Untracked files
” 部分。
🤔 使用
git add 文件名
命令是否意味着该文件已经被纳入Git 监管(已被Git 跟踪)?
是的,使用命令会将文件 ‘c.txt’ 添加到 Git 的跟踪列表中,标记为已追踪(tracked)。
当运行 git add
命令时,Git 会将指定的文件从工作区添加到暂存区。暂存区是一个缓冲区域,用于暂时存储要包含在下一次提交中的更改。通过将文件添加到暂存区,Git 开始跟踪该文件的状态变化,即文件的新修改或删除操作。这意味着 Git 将在下一次提交时记录并保存对文件的更改。
所以,一旦使用 git add c.txt
将文件添加到 Git 的跟踪列表,该文件就被视为已追踪。接下来,你可以使用 git commit
命令将暂存区中的更改提交到版本历史记录中。
需要注意的是,如果在运行 git add
命令之前没有创建过该文件,那么该文件将被识别为新文件,并添加到 Git 的跟踪列表中。如果在运行 git add
命令之前对文件进行了修改,则 git add
命令将记录这些修改并更新版本控制系统。
👉举例演示
新建一个文件c.txt,使用vim修改该文件,第一次修改后add到缓存区中,第二次修改后不add和commit,然后使用git checkout --文件名命令进行文件撤销
①新建文件c.txt并使用vim修改它,插入“你好,世界!”,第一次修改后add到缓存区中
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ vim c.txt
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ cat c.txt
你好,世界!
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ git checkout c.txt
error: pathspec 'c.txt' did not match any file(s) known to git
②第二次修改该文件,插入“你好,Git!”,然后使用git checkout --文件名命令进行文件撤销
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ vim c.txt
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ cat c.txt
你好,世界!
你好,Git!
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ git checkout c.txt
Updated 1 path from the index
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ cat c.txt
你好,世界!
我们可以很明显的看到,c.txt文件已被恢复到第一次修改时的状态,即文件中只有一条数据【你好,世界】!!!
🚩情形二(已add,未commit的文件)
👉命令
git reset HEAD <文件名>
:将已经添加到暂存区(或索引)的文件移出暂存区git reset HEAD .
:撤销所有已添加到暂存区的文件,可以使用.
作为文件名
👉举例演示
使用vim修改文件c.txt,d.txt和e.txt,添加add,但不提交commit,使用上述命令进行撤销
①使用git reset HEAD c.txt命令将c.txt移出缓存区
②使用git reset HEAD . 命令将剩余的两个文件一起移出缓存区
💡注意
git reset HEAD
命令只影响暂存区,不会修改工作区中的实际文件内容。如果需要撤销对文件的修改并还原到最近一次提交的状态,可以使用git checkout -- <文件名>
命令。
2.5 删除
👉可以使用
git rm
命令。git rm
命令会将文件从 Git 仓库中删除,并将删除操作记录到提交历史中。
以下是删除文件的几种常见情况和对应的命令:
-
删除工作目录中的文件并将删除操作提交到 Git 仓库
git rm <文件名>
将
<文件名>
替换为要删除的文件的名称。例如,要删除名为c.txt
的文件,命令如下:git rm c.txt
运行该命令后,文件将被从工作目录和 Git 仓库中删除。
举例演示:将文件c.txt使用
git rm c.txt
命令删除①先将文件c.txt提交到本地版本库中
②t使用
git rm c.txt
命令删除此文件 -
仅删除 Git 仓库中的文件,而不删除工作目录中的文件
git rm --cached <文件名>
使用
--cached
选项可以仅将文件从 Git 仓库中删除,而保留工作目录中的实际文件。例如,要从 Git 仓库中删除名为
c.txt
的文件,但保留工作目录中的实际文件,命令如下:git rm --cached c.txt
运行该命令后,文件将被从 Git 仓库中删除,但保留在工作目录中。
举例演示:使用git rm --cached d.txt命令删除文件d.txt
①先把文件d.txt添加到git仓库中
②使用git rm --cached d.txt命令删除文件d.txt
-
删除整个文件夹及其内容:
git rm -r <文件夹路径>
使用
-r
选项可以递归地删除文件夹及其内容。例如,要删除名为
folder
的文件夹及其所有内容,命令如下:git rm -r folder
运行该命令后,文件夹及其内容将被从工作目录和 Git 仓库中删除。
举例演示:在该项目所在的文件夹中新建一个文件夹folder,使用git rm -r folder命令删除该文件夹
①在该项目所在的文件夹中新建一个文件夹folder,并提交到git仓库中
②使用git rm -r folder命令删除该文件夹
在执行 git rm
命令后,需要通过提交操作来确认删除 ,需要使用 git commit
命令提交你的更改,并将删除操作记录到提交历史中。
why?
这是因为
git rm
命令会把删除操作添加到暂存区,但实际的文件删除操作只会在提交时生效。
注意
git rm
命令不仅会从 Git 仓库中删除文件,还会将删除操作添加到暂存区。如果只想保留文件在 Git仓库中但从工作目录中删除,可以使用git rm --cached
命令。
2.6 分支
几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。Git 的master分支并不是一个特殊分支。 它跟其它分支没有区别。 之所以几乎每一个仓库都有 master 分支,是因为git init 命令默认创建它,并且大多数人都懒得去改动它。
2.6.1 实际开发流程
2.6.2 分支概念
在使用版本控制工具【git / svn 】开发的过程中,可以同时推进多个任务,如下图所示
2.6.3. 分支的好处
①可以同时并行推进多个功能开发,提高开发效率
②各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响。失败的分支删除重新开始即可。
2.6.4 分支操作
命令名称 | 作用 |
---|---|
git branch 分支名 | 创建分支 |
git branch -v | 查看分支 |
git checkout 分支名 | 切换分支 |
git merge 分支名 | 把指定的分支合并到当前分支上 |
2.6.5 分支操作详解
1) 创建分支和切换分支之图解
解读
- master,hotfix其实都是指向具体版本记录的指针。当前所在的分支,其实是由HEAD决定的
- HEAD如果指向master,那么我们现在就在master分支上
- HEAD如果指向hotfix,那么我们现在就在hotfix分支上
- 切换分支的本质就是移动HEAD指针
2) 如何创建分支和切换分支?
①创建分支
👉前提
你已在本地仓库的主分支(一般是
master
)
🤔如何确保当前所在分支是是主分支?
通过命令
git branch
来确认当前所在分,当前所在的分支会在列表中以特殊标记(通常是*
)显示出来
👉命令
git branch <新分支名>
👉举例演示
创建分支test
②切换分支
👉切换到新创建的分支,可以使用以下命令:
git checkout <新分支名>
👉举例演示
要切换到名为
test
的新分支
💡注意
如果你使用的是较新版本的 Git(2.23+),也可以使用以下命令创建并切换到新分支:
git switch -c <新分支名>
👉举例演示
使用git switch -c <新分支名> 命令创建新分支test1
3)如何删除分支?
👉删除分支之前需通过git branch命令确定要删除的分支名称,然后执行以下命令:
git branch -d <分支名>
👉举例演示
要删除名为
test1
的分支,可以运行以下命令:
git branch -d test1
💡注意
删除分支只会删除对应的分支引用,而不会删除与该分支关联的提交历史。因此,删除分支并不会造成数据丢失,可以放心执行。
4) 如何合并分支?
👉图解如下所示:
合并分支时会涉及到两个分支。这两个分支一个是“当前所在分支”,一个是“目标分支”
👉命令
git merge 目标分支
此命令的本质就是把目标分支合并到当前所在分支。
👉举例演示
把分支hotfix合并到test分支中
①确保当前所在的分支是test
②使用git merge hotfix命令将分支hotfix合并到当前分支test上
2.7 git追踪的文件数据丢失了,怎么办?
1.问题描述
我在分支test上修改文件abc.txt,修改完后提交到git仓库,但是切回master分支时vim
abc.txt文件时,文件中没有数据,是空白的
①在test分支上查看文件abc.txt,其内容如下
②在master分支上查看文件abc.txt,其内容如下
2.问题原因
①操作失误
:删除了一个错误的分支可能会导致数据丢失,在删除分支之前,确保选择了正确的分支。
②使用错误的分支合并
:当使用Git进行分支合并时,有时候会选择错误的分支或提交。如果在错误的分支上执行合并操作,可能会导致数据丢失,因为合并会更新当前分支的提交记录。
③磁盘故障
:Git的数据存储在硬盘上。如果硬盘发生故障,可能会导致git仓库的部分或全部数据丢失
3.解决方案
👉步骤
①使用
git reflog <文件名/文件路径>
/git reflog
命令检查 Git 的提交历史记录,确认文件是否在之前的提交中存在
②如果你找到了包含丢失数据的提交,则通过回退该提交来恢复丢失的版本。使用
git checkout
命令将文件恢复到特定提交的状态
命令参考如下:
git checkout <目标提交> -- <文件路径>
替换 <目标提交>
为包含丢失数据的提交的哈希值或相对引用,<文件路径>
为丢失数据的文件路径
简而言之,就是把历史操作记录中每一行记录最左边的”编号"[哈希值或相对引用],例如“6621c2e ”之类的,放到<目标提交>的位置,在当前位置上的文件,可直接写文件名在<文件路径>上的位置
2.8 版本冲突
1. 冲突产生的表现
举例演示:
①创建分支test,并在此分支上新建并修改文件abc.txt,提交到git仓库中
代码示例如下:
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ git checkout test
Switched to branch 'test'
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (test)
$ vim abc.txt
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (test)
$ cat abc.txt
你好,世界!
风调雨顺
你好,Java!
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (test)
$ git add abc.txt
warning: in the working copy of 'abc.txt', LF will be replaced by CRLF the next time Git touches it
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (test)
$ git commit -m "test分支修改了第二行数据"
[test 67ca5a4] test分支修改了第二行数据
1 file changed, 3 insertions(+)
create mode 100644 abc.txt
②切回主分支master,并在此分支上修改文件abc.txt,主要是对文件abc.txt中第二行数据修改为“xxxx”,最后提交到git仓库中
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (test)
$ git checkout master
Switched to branch 'master'
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ cat abc.txt
你好,世界!
风调雨顺
你好,Java!
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ vim abc.txt
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ cat abc.txt
你好,世界!
xxxx
你好,Java!
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ git commit -am "master修改了第二行数据"
[master 7766fc2] master修改了第二行数据
1 file changed, 3 insertions(+)
create mode 100644 abc.txt
③把test分支合并到master分支上
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master)
$ git merge test
Auto-merging abc.txt
CONFLICT (add/add): Merge conflict in abc.txt
Automatic merge failed; fix conflicts and then commit the result.
king@DESKTOP-F03JAPH MINGW64 ~/Desktop/git_test (master|MERGING)
$ cat abc.txt
你好,世界!
<<<<<<< HEAD
xxxx
=======
风调雨顺
>>>>>>> test
你好,Java!
Git使用“<<<<<<< HEAD、=========、>>>>>>>>>> 分支名称”符号帮我们标记出产生冲突的内容
具体冲突内容如下所示:
2. 冲突产生的原因
合并分支时,两个分支在同一个文件的同一个位置有两套完全不同的修改。Git无法替我们决定使用哪一个。必须人为决定新代码内容。
3. 冲突的解决
①编辑有冲突的文件,删除特殊符号,决定要使用的内容
②添加到暂存区
③执行提交(注意:使用git commit命令时不能带文件名)
4. 避免冲突
👉容易冲突的操作方式
-
多个人同时操作了同一个文件
-
一个人一直写不提交
-
修改之前不更新最新代码
-
提交之前不更新最新代码
-
擅自修改同事代码
👉减少冲突的操作方式
-
养成良好的操作习惯,先
pull
在修改,修改完立即commit
和push
-
一定要确保自己正在修改的文件是最新版本的
-
各自开发各自的模块
-
如果要修改公共文件,一定要先确认有没有人正在修改
-
下班前一定要提交代码,上班第一件事拉取最新代码
-
一定不要擅自修改同事的代码