目录
一、Git下载
下载链接:https://git-scm.com/download/win
安装步骤:直接next就好了。
具体教程:鱼C论坛
二、初次使用Git前的配置
在命令行里输入以下命令
设置用户名:git config --global user.name "xxx"
设置邮箱:git config --global user.email "xxx@xx.com"
查看当前用户:git config --list
三、理论基础
Git记录的是什么?
Git将每个版本独立保存。
Git 的核心框架——“三棵树”。
这三棵树分别是:工作区域、暂存区域和 Git 仓库
Git 的工作流程:
在工作目录中添加、修改文件;
将需要进行版本管理的文件放入暂存区域;
将暂存区域的文件提交到 Git 仓库。
四、实战
1. 新建仓库
1. 打开命令行,进入项目所在的文件夹(例:G:\MyProject)。
2. 创建一个空的Git仓库
git init
3. 创建完成之后,文件夹中会有一个.git
文件夹,如果看不到就点文件夹的查看,把“隐藏的项目”勾选上,就可以看到了。
2. 将文件放入暂存区域
在文件夹内创建一个README.md
文件,将该文件放入暂存区域。在命令行输入
git add README.md
3. 将文件提交到Git仓库
git commit -m "add a REDAME file"
4. 查看状态
git status
5. 取消对暂存区的操作,暂存区恢复为上一次的状态
git restore --staged LICENSE.txt
6. 在本地对文件进行了修改
-
使用
git restore LICENSE
。修改后的文件会被之前暂存区内的文件覆盖。 -
使用
git add LICENSE
。修改后的文件会覆盖之前暂存区内的文件。
7. 修改文件
如果之前修改文件已经添加到暂存区,但是还未提交到Git仓库,此时在本地再次修改了文件,此时就有三个版本(本地,暂存区,仓库)。
-
如果要修改暂存区,就使用
git add
命令。 -
如果要修改仓库,就先
git add
到暂存区,再git commit -m "change a LICENSE file"
提交到仓库。
8. 查看历史提交
git log
9. reset命令的选项(版本回滚)
get reset HEAD~ // `~`代表回退一次,`~10`代表回退10次 get reset --mixed HEAD~ // 等同于上一条命令,`--mixed`是默认的
移动HEAD的指向,将其指向上一个快照
将HEAD移动后指向的快照回滚到暂存区域
git reset --soft HEAD~
移动HEAD的指向,将其指向上一个快照(相当于撤销上一次的错误提交命令)
git reset --hard HEAD~
移动HEAD的指向,将其指向上一个快照
将HEAD移动后指向的快照回滚到暂存区域
将暂存区域的文件还原到工作目录
reset命令回滚快照三部曲
-
移动HEAD的指向(--soft)
-
将快照回滚到暂存区域([--mixed],默认)
-
将暂存区域还原到工作目录(--hard)
10. 回滚指定快照
不仅可以回滚,还可以前滚(注意:--soft,--mixed,--hard)
git reset 版本快照的ID号 //ID号至少五位以上
11. 回滚个别文件
注意:--soft,--mixed,--hard
git reset 版本快照 文件名/路径
12. 查看版本快照ID
git reflog
五、版本对比
1. 解决Git显示中文乱码的问题
-
在命令窗口输入以下命令
git config --global core.quotepath false # 设置 git status utf-8编码
git config --global gui.encoding utf-8 # 设置Git GUI界面utf-8编码
git config --global i18n.commit.encoding utf-8 #设置commit信息utf-8编码
git config --global i18n.logoutputencoding utf-8 # 设置输出 log utf-8 编码
-
新建系统环境变量 LESSCHARSET并赋值为utf-8。
-
注销电脑重新进入即可。
2. 比较暂存区域与工作目录
git diff
-
表示旧文件
+
表示新文件按键
j
往下移动一行按键
k
往上移动一行按键
f
往下移动一页按键
b
往上移动一页按键
d
往下移动半页按键
u
往上移动半页按键
g
跳转到第一行按键
G
跳转到最后一行
按键
n
下一个关键字按键
N
上一个关键字按键
h
打开帮助文档
3. 比较两个历史版本
git diff 快照ID1 快照ID2
4. 比较当前工作目录和Git仓库中的快照
git diff 快照ID1
5. 比较最新提交的快照和当前工作目录
git diff HEAD
6. 比较暂存区和Git仓库中的快照
git diff --cached [快照ID]
六、修改文件
1. 修改最后一次提交文件
git commit --amend
进入修改,操作同vim
编辑器。
git commit --amend -m "修改内容"
2. 恢复最后一次在工作目录删除的文件
git restore 文件名
3. 删除在工作目录的文件
-
该命令删除的只是工作目录和暂存区域的文件,也就是取消跟踪,在下次提交时不纳入版本管理。
git rm 文件名
-
当修改之前的文件已经添加到暂存区,此时在工作目录修改了文件,此时要删除修改后的文件,使用
git rm
命令无法删除,可以使用git rm -f
强制删除。
4. 只删除暂存区文件,不删除工作目录文件
git rm --cached 文件名
5. 重命名文件
git mv 旧文件名 新文件名
七、Git分支
1. 创建分支
git branch 分支名
git log --decorate // 让log显示指向这个提交的索引分支或标签(git log也可以显示)
git log --online // 每个快照只显示一行
git log --oneline --graph --all // 每个快照只显示一行,以图形化显示所有快照(包括分支)
2. 切换分支
git chekout 分支名
3. 合并分支
git merge 分支名
-
如果提示合并失败,则需要手动合并,修改有不同的文件,重新上传并提交仓库。
git checkout -b 分支名 // 创建并切换分支
4. 删除分支
git branch -d 分支名 // -d是简写,--delete是全称
5. 匿名分支
git checkout HEAD~
你使用了checkout
命令但没有指定分支名,所以 Git 帮你创建了一个匿名分支。既然是匿名,那么当你切换到别的分支时,这个匿名分支中的所有提交都会被丢弃掉。因此,你可以利用匿名分支来做做实验什么的,反正不会有负面影响。
八、再论 checkout
事实上呢,checkout 命令有两种功能:
-
从历史快照(或者暂存区域)中拷贝文件到工作目录
-
切换分支
1. 从历史快照(或者暂存区域)中拷贝文件到工作目录
当给定某个文件名时,Git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如执行 `git checkout HEAD~ README.md `命令会将上一个快照中的`README.md` 文件复制到工作目录和暂存区域中:
如果命令中没有指定具体的快照 ID,则将从暂存区域恢复指定文件到工作目录git checkout README.md
:
有些朋友可能会问:“上次看你在文件名的前边有加两个横杆(--),这次怎么就没有了呢?”
问得好,Git 提醒你写成 git checkout -- README.md
的形式,那是为了预防你恰好有一个分支叫做 README.md
,那么它就搞不懂你要恢复文件还是切换分支了,所以约定两个横杆(--)后边跟的是文件名。
反过来说,如果你确保你没有一个叫做 README.md 的分支,你直接写 git checkout README.md
也是没问题的。
2. 切换分支
首先我们知道 Git 的分支其实就是添加一个指向快照的指针,其次我们还知道切换分支除了修改 HEAD 指针的指向,还会改变暂存区域和工作目录的内容。
所以执行git checkout 373c0
命令,Git 主要就是做了下边这两件事(当然事实上 Git 还做了更多):
那回过头来,如果我们只想恢复指定的文件/路径,那么我们只需要指定具体的文件,Git 就会忽略第一步修改 HEAD 指向的操作,这不正跟之前讲 reset 命令的时候一样吗?
checkout 命令和 reset 命令的区别
恢复文件
checkout 命令和 reset 命令都可以用于恢复指定快照的指定文件,并且它们都不会改变 HEAD 指针的指向。
下面开始划重点:
它们的区别是 reset 命令只将指定文件恢复到暂存区域(--mixed),而 checkout 命令是同时覆盖暂存区域和工作目录。
注意:也许你试图使用 git reset --hard HEAD~ README.md 命令让 reset 同时覆盖工作目录,但 Git 会告诉你这是徒劳(此时 reset 不允许使用 --soft 或 --hard 选项)。
这样看来,在恢复文件方面,reset 命令要比 checkout 命令更安全一些。
恢复快照
reset 命令是用来“回到过去”的,根据选项的不同,reset 命令将移动 HEAD 指针(--soft) -> 覆盖暂存区域(--mixed,默认)-> 覆盖工作目录(--hard)。
checkout 命令虽说是用于切换分支,但前面你也看到了,它事实上也是通过移动 HEAD 指针和覆盖暂存区域、工作目录来实现的。
那问题来了:它们有什么区别呢?
下面开始划重点:
-
第一个区别是,对于 reset --hard 命令来说,checkout 命令更安全。因为 checkout 命令在切换分支前会先检查一下当前的工作状态,如果不是“clean”的话,Git 不会允许你这样做;而 reset --hard 命令则是直接覆盖所有数据。
-
另一个区别是如何更新 HEAD 指向,reset 命令会移动 HEAD 所在分支的指向,而 checkout 命令只会移动 HEAD 自身来指向另一个分支。
看文字你肯定懵,我们举例说明。
来,大家先把刚才的例子改成下边这样:
执行 git checkout feature
命令:
可以看到只是 HEAD 指针跑到 feature 分支那儿去了。
好,我们执行git checkout master
命令将其切回。
现在执行git reset --hard feature
命令:
看到区别了吗?
reset 命令将 HEAD 指向的分支以及 HEAD 本身都切到了 feature 分支里,换句话说,原来的快照已经被消失了(5.txt 那个快照不见了)。
通常情况下,Git 会尽可能地尝试使用 Fast-forward 方式来合并分支,因为这样效率非常高,只有在万不得已的时候才使用三方合并。
但是,有时候 Fast-forward 的方式却很容易让我们忽略了分支的存在!
举个例子,比如下面这样:
如果我们把“feature”分支删除,就会直接丢掉分支的信息:
根本就不知道有个分支存在过……
可有时候我们确实希望保留分支的信息,应该怎么办呢?
只需要在 merge 的时候使用 --no-ff 选项即可告诉 Git 不要使用 Fast-forward 方式合并分支。
这样 Git 就会乖乖地使用三方合并(Three-way merge):
OK,这样就算删掉了“feature”分支,我们仍然可以很容易看出有个分支曾经存在过: