目录
- 一、课程目标
- 二、初始Git
- 三、安装Git
- 3.1 Linux-centos
- 四、Git的基本操作
- 4.1 创建Git本地仓库
- 五、配置Git
- 六、认识工作区、暂存区、版本库
- 七、添加文件
- 八、查看.git
- 九、修改文件
- 十、版本回退
- 十一、撤销修改
- 11.1 情况一:对于工作区的代码,还有add
- 11.2 情况二:已经add,但没有commit
- 11.2 情况三:已经add,并且也commit了
- 十二、删除文件
一、课程目标
1.技术⽬标:掌握Git企业级应⽤,深刻理解Git操作过程与操作原理,理解⼯作区,暂存区,版本库
的含义。
2.技术⽬标:掌握Git版本管理,⾃由进⾏版本回退、撤销、修改等Git操作⽅式与背后操作原理。
3.技术⽬标:掌握Git分⽀管理,从分⽀创建,切换,合并,删除的整个⽣命周期,灵活进⾏各种场景下的分⽀管理,学习常⻅分⽀管理策略。
4.技术⽬标:掌握Git远程仓库与本地仓库,结合版本管理与分⽀管理,做到基于分⽀级的个⼈级开发。
5.技术⽬标:理解分布式版本控制系统,学习远程仓库与本地仓库的交互操作,掌握多⼈协作开发模
式。
6.协作⽬标:学习企业级常⻅分⽀策略(master/release/develop/feature/hotfix等),理解不同企业,不同环境下适合的分⽀模型。结合案例,引⼊⼯程师,测试⼈员,技术经理等⻆⾊,展现项⽬开发过程的全貌,深刻理解开发的整体流程,俯视Git在其中的作⽤。
二、初始Git
为了能够更⽅便我们管理这些不同版本的⽂件,便有了版本控制器。所谓的版本控制器,就是能让你了解到⼀个⽂件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录⼯程的每⼀次改动和版本迭代的⼀个管理系统,同时也⽅便多⼈协同作业。
⽬前最主流的版本控制器就是Git。Git可以控制电脑上所有格式的⽂件,例如doc、excel、dwg、dgn、rvt等等。对于我们开发⼈员来说,Git最重要的就是可以帮助我们管理软件开发项⽬中的源代码⽂件!
注意:
还需要再明确⼀点,所有的版本控制系统,Git也不例外,其实只能跟踪⽂本⽂件的改动,⽐如TXT⽂件,⽹⻚,所有的程序代码等等。版本控制系统可以告诉你每次的改动,⽐如在第5⾏加了⼀个单词
“Linux”,在第8⾏删了⼀个单词“Windows”。
⽽图⽚、视频这些⼆进制⽂件,虽然也能由版本控制系统管理,但没法跟踪⽂件的变化,只能把⼆进制⽂件每次改动串起来,也就是只知道图⽚从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
三、安装Git
3.1 Linux-centos
如果你的的平台是centos,安装git相当简单,以centos7.6为例:
⾸先,你可以试着输⼊Git,看看系统有没有安装Git:
$ git
-bash: git: command not found
出现像上⾯的结果,Linux会友好地告诉你Git没有安装。
安装Git:
sudo yum -y install git
查看Git安装的版本:
git --version
可以看到我的版本十1.8.3.1
四、Git的基本操作
4.1 创建Git本地仓库
要提前说的是,仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂件进⾏版本控制,就必须先创建⼀个仓库出来。
创建⼀个Git本地仓库对应的命令为git init ,注意命令要在⽂件⽬录下执⾏,例如:
[zl@VM-16-2-centos lesson]$ git init
Initialized empty Git repository in /home/zl/Git/lesson/.git/
[zl@VM-16-2-centos lesson]$ ls
[zl@VM-16-2-centos lesson]$ ls -a
. .. .git
[zl@VM-16-2-centos lesson]$ tree .git/
.git/
|-- branches
|-- config
|-- description
|-- HEAD
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- prepare-commit-msg.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| `-- update.sample
|-- info
| `-- exclude
|-- objects
| |-- info
| `-- pack
`-- refs
|-- heads
`-- tags
9 directories, 13 files
我们发现,当前⽬录下多了⼀个 .git 的隐藏⽂件, .git ⽬录是Git来跟踪管理仓库的,不要⼿动修改这个⽬录⾥⾯的⽂件,不然改乱了,就把Git仓库给破坏了。
五、配置Git
当安装Git后⾸先要做的事情是设置你的⽤⼾名称和e-mail地址,这是⾮常重要的。配置命令为:
[zl@VM-16-2-centos lesson]$ git config user.name "Your Name"
[zl@VM-16-2-centos lesson]$ git config user.email "email@example.com"
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可。
其中 --global 是⼀个可选项。如果使⽤了该选项,表⽰这台机器上所有的Git仓库都会使⽤这个
配置。如果你希望在不同仓库中使⽤不同的name或 e-mail ,可以不要 --global 选项,但要注意的是,执⾏命令时必须要在仓库⾥。
查看配置命令为:
git config -l
删除对应的配置命令为:
git config [--global] --unset user.name
git config [--global] --unset user.email
六、认识工作区、暂存区、版本库
1.⼯作区:是在电脑上你要写代码或⽂件的⽬录。
2.暂存区:英⽂叫stage或index。⼀般存放在 .git ⽬录下的index⽂件(.git/index)中,我们把暂存区有时也叫作索引(index)。
3.版本库:⼜名仓库,英⽂名repository 。⼯作区有⼀个隐藏⽬录.git ,它不算⼯作区,⽽是Git的版本库。这个版本库⾥⾯的所有⽂件都可以被Git管理起来,每个⽂件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
下⾯这个图展⽰了⼯作区、暂存区和版本库之间的关系:
1.图中左侧为⼯作区,右侧为版本库。Git的版本库⾥存了很多东西,其中最重要的就是暂存区。
2.在创建Git版本库时,Git会为我们⾃动创建⼀个唯⼀的master分⽀,以及指向master的⼀个指针叫HEAD。(分⽀和HEAD的概念后⾯再说)
3.当对⼯作区修改(或新增)的⽂件执⾏git add命令时,暂存区⽬录树的⽂件索引会被更新。
4.当执⾏提交操作 git commit 时,master分⽀会做相应的更新,可以简单理解为暂存区的⽬录树才会被真正写到版本库中。
由上述描述我们便能得知:通过新建或粘贴进⽬录的⽂件,并不能称之为向仓库中新增⽂件,⽽只是在⼯作区新增了⽂件。必须要通过使⽤git add和git commit命令才能将⽂件添加到仓库中进⾏管理!
七、添加文件
在包含.git的⽬录下新建⼀个readme⽂件,我们可以使⽤ git add 命令可以将⽂件添加到暂存区:
1.添加⼀个或多个⽂件到暂存区: git add [file1] [file2] …
2.添加指定⽬录到暂存区,包括⼦⽬录: git add [dir]
3.添加当前⽬录下的所有⽂件改动到暂存区: git add .
再使⽤ git commit 命令将暂存区内容添加到本地仓库中:
1.提交暂存区全部内容到本地仓库中: git commit -m “message”
2.提交暂存区的指定⽂件到仓库区: git commit [file1] [file2] … -m “message”
注意 git commit后⾯的 -m 选项,要跟上描述本次提交的message,由用户自己完成,这部分内容绝对不能省略,并要好好描述,是⽤来记录你的提交细节,是给我们⼈看的。
[zl@VM-16-2-centos lesson]$ ls -a
. .. .git
[zl@VM-16-2-centos lesson]$ touch readme
[zl@VM-16-2-centos lesson]$ git add readme
[zl@VM-16-2-centos lesson]$ git commit -m "message"
[master (root-commit) f2b4f93] message
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 readme
git commit 命令执⾏成功后会告诉我们,1个⽂件被改动(就是我们新添加的ReadMe⽂件),插⼊了零⾏内容(ReadMe有零⾏内容)。
我们还可以多次add不同的⽂件,⽽只commit⼀次便可以提交所有⽂件,是因为需要提交的⽂件是通通被add到暂存区中,然后⼀次性commit暂存区的所有修改。
[zl@VM-16-2-centos lesson]$ touch file1 file2
[zl@VM-16-2-centos lesson]$ git add file1 file2
[zl@VM-16-2-centos lesson]$ git commit -m "add 2 files"
[master de1b4c8] add 2 files
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file1
create mode 100644 file2
截⾄⽬前为⽌,我们已经更够将代码直接提交⾄本地仓库了。我们可以使⽤ git log 命令,来查看下历史提交记录:
[zl@VM-16-2-centos lesson]$ git log
commit de1b4c8366525177d4df108a0eeafebcf97baad2
Author: sushangzl <939712250@qq.com>
Date: Sat Apr 20 22:36:13 2024 +0800
add 2 files
commit f2b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b
Author: sushangzl <939712250@qq.com>
Date: Sat Apr 20 22:30:20 2024 +0800
message
该命令显⽰从最近到最远的提交⽇志,并且可以看到我们commit时的⽇志消息。如果嫌输出信息太多,看得眼花缭乱的,可以试试加上 --pretty=oneline 参数:
需要说明的是,我们看到的⼀⼤串类似 23807c5…56eed6 的是每次提交的 commit id (版本号),Git的 commit id 不是1,2,3……递增的数字,⽽是⼀个SHA1计算出来的⼀个⾮常⼤的数字,⽤⼗六进制表⽰(你看到的 commit id 和我的肯定不⼀样,以你⾃⼰的为准)。
八、查看.git
[zl@VM-16-2-centos lesson]$ tree .git
.git
|-- branches
|-- COMMIT_EDITMSG
|-- config
|-- description
|-- HEAD
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- prepare-commit-msg.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| `-- update.sample
|-- index
|-- info
| `-- exclude
|-- logs
| |-- HEAD
| `-- refs
| `-- heads
| `-- master
|-- objects
| |-- 26
| | `-- 65a71efc3cbe102d836e801179a75ba789ae5c
| |-- de
| | `-- 1b4c8366525177d4df108a0eeafebcf97baad2
| |-- e6
| | `-- 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
| |-- e8
| | `-- 0ad49ace82167de62e498622d70377d913c79e
| |-- f2
| | `-- b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b
| |-- info
| `-- pack
`-- refs
|-- heads
| `-- master
`-- tags
17 directories, 23 files
1.index 就是我们的暂存区,add后的内容都是添加到这⾥的。
2.HEAD 就是我们的默认指向master分⽀的指针:
3.objects 为Git的对象库,⾥⾯包含了创建的各种版本库对象及内容。当执⾏git add命令时,暂存区的⽬录树被更新,同时⼯作区修改(或新增)的⽂件内容被写⼊到对象库中的⼀个新的对象中,就位于".git/objects"⽬录下。
九、修改文件
Git⽐其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,⽽⾮⽂件。
什么是修改?⽐如你新增了⼀⾏,这就是⼀个修改,删除了⼀⾏,也是⼀个修改,更改了某些字符,也是⼀个修改,删了⼀些⼜加了⼀些,也是⼀个修改,甚⾄创建⼀个新⽂件,也算⼀个修改。让我们将ReadMe⽂件进⾏⼀次修改:
此时,仓库中的ReadMe和我们⼯作区的ReadMe是不同的,如何查看当前仓库的状态呢? git
status 命令⽤于查看在你上次提交之后是否有对⽂件进⾏再次修改。
[zl@VM-16-2-centos lesson]$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme
#
no changes added to commit (use "git add" and/or "git commit -a")
上⾯的结果告诉我们,readme被修改过了,但还没有完成添加与提交。
⽬前,我们只知道⽂件被修改了,如果能知道具体哪些地⽅被修改了,就更好了。
[zl@VM-16-2-centos lesson]$ git diff readme
diff --git a/readme b/readme
index e69de29..3b18e51 100644
--- a/readme
+++ b/readme
@@ -0,0 +1 @@
+hello world
git diff [file] 命令⽤来显⽰暂存区和⼯作区⽂件的差异,显⽰的格式正是Unix通⽤的diff格式。也可以使⽤ git diff HEAD – [file] 命令来查看版本库和⼯作区⽂件的区别。
[zl@VM-16-2-centos lesson]$ git add readme
[zl@VM-16-2-centos lesson]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: readme
#
git add 之后,就没有看到上⾯ no changes added to commit (use “git add” and/or “git commit -a”) 的消息了。接下来让我们继续 git commit 即可:
[zl@VM-16-2-centos lesson]$ git commit -m "modify readme"
[master b879e4f] modify readme
1 file changed, 1 insertion(+)
[zl@VM-16-2-centos lesson]$ git status
# On branch master
nothing to commit, working directory clean
十、版本回退
之前我们也提到过,Git能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现之前前的⼯作做的出现了很⼤的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。
执⾏ git reset命令⽤于回退版本,可以指定退回某⼀次提交的版本。要解释⼀下“回退”本质是要将版本库中的内容进⾏回退,⼯作区或暂存区是否回退由命令参数决定:
git reset 命令语法格式为: git reset [–soft | --mixed | --hard] [HEAD]
还可以回退到当前版本,就是版本库中是什么样的,工作区和暂存区就会回退到什么样的
1.–mixed为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内容,⼯作区⽂件保持不变。
2.–soft参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
3.–hard参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
HEAD 说明:
可直接写成commit id,表⽰指定退回的版本
HEAD 表⽰当前版本
HEAD^ 上⼀个版本
HEAD^^ 上上⼀个版本
以此类推…
[zl@VM-16-2-centos lesson]$ ls
file1 file2 readme
[zl@VM-16-2-centos lesson]$ git log --pretty=oneline
b879e4f12400129cedabecb18f4f15238558f539 modify readme
de1b4c8366525177d4df108a0eeafebcf97baad2 add 2 files
f2b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b message
从日志中可以看到,我们提交了三次代码的信息,但是在我们提交完后,发现最后提交的版本编译错误,想回到前面的版本,重新基于前面的版本编写。由于我们这里希望的是将工作区的内容也回到前面的版本,所以需要用到- -hard参数
[zl@VM-16-2-centos lesson]$ git reset --hard f2b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b
HEAD is now at f2b4f93 message
[zl@VM-16-2-centos lesson]$ ls
readme
[zl@VM-16-2-centos lesson]$ git log --pretty=oneline
f2b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b message
此时,我们的文件内容,已经回到了一开始的版本了,当前我们再用git log查看一个日志,发现只有一个版本了
但是,如果我们现在后悔了改怎么办,想要回到原来最新的版本,我们可以继续使用git reset命令,回到最新的版本,但是我们必须要拿到最新版本的commit id去指定回退的版本。
[zl@VM-16-2-centos lesson]$ git reset --hard b879e4f12400129cedabecb18f4f15238558f539
HEAD is now at b879e4f modify readme
[zl@VM-16-2-centos lesson]$ ls
file1 file2 readme
[zl@VM-16-2-centos lesson]$ git log --pretty=oneline
b879e4f12400129cedabecb18f4f15238558f539 modify readme
de1b4c8366525177d4df108a0eeafebcf97baad2 add 2 files
f2b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b message
假如我们没有办法在以前的记录中获取到commit id的信息。git还提供了一个git reflog命令能补救一下,该命令用来记录本地的每一次命令
[zl@VM-16-2-centos lesson]$ git reflog
b879e4f HEAD@{0}: reset: moving to b879e4f12400129cedabecb18f4f15238558f539
f2b4f93 HEAD@{1}: reset: moving to f2b4f93c8d4ad943dbf80ee0a49feaf2fcbbd61b
b879e4f HEAD@{2}: commit: modify readme
de1b4c8 HEAD@{3}: commit: add 2 files
f2b4f93 HEAD@{4}: commit (initial): message
这样就可以很方便的找到你的所有操作记录了,虽然这次版本的commit id只有一部分。但是在git版本回退的时候,也可以使用部分commit id来代表目标版本。
值得说的是,Git的版本回退速度⾮常快,因为Git在内部有个指向当前分⽀(此处是master)的HEAD指针, refs/heads/master ⽂件⾥保存当前 master 分⽀的最新 commit id 。当我们在回退版本的时候,Git仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解成如下⽰意图:
十一、撤销修改
11.1 情况一:对于工作区的代码,还有add
你当然可以直接删掉你⽬前在⼯作区新增的代码
⾟亏我们⼯作效率不⾼,才写了⼀⾏代码就发现不⾏了,要是你写了3天,⼀直都没有提交,该怎么删掉呢?你⾃⼰都忘了⾃⼰新增过哪些,有同学说,我可以 git diff xxx ⼀下,看看差别在删啊,那你肯定⼜要花3天时间删代码了,并且很⼤的概率还会改出bug。
Git其实还为我们提供了更好的⽅式,我们可以使⽤ git checkout – [file] 命令让⼯作区的⽂件回到最近⼀次 add 或 commit 时的状态。要注意** git checkout – [file]** 命令中的-- 很重要,切记不要省略,⼀旦省略,该命令就变为其他意思了,后⾯我们再说。⽰例如下:
[zl@VM-16-2-centos lesson]$ vim readme
[zl@VM-16-2-centos lesson]$ ls
file1 file2 readme
[zl@VM-16-2-centos lesson]$ cat readme
hello world
hello git
xxxx
[zl@VM-16-2-centos lesson]$ git checkout -- readme
[zl@VM-16-2-centos lesson]$ cat readme
hello world
11.2 情况二:已经add,但没有commit
add后还是保存到了暂存区呢?怎么撤销呢?
让我们来回忆⼀下学过的 git reset回退命令,该命令如果使⽤**–mixed参数,可以将暂存区的内容退回为指定的版本内容,但⼯作区⽂件保持不变。那我们就可以回退下暂存区的内容了!!!
⽤git status**查看⼀下,发现现在暂存区是⼲净的,⼯作区有修改。
还记得如何丢弃⼯作区的修改吗?(撤销修改,回到最近的版本) git checkout – readme
[zl@VM-16-2-centos lesson]$ vim readme
[zl@VM-16-2-centos lesson]$ git add readme
[zl@VM-16-2-centos lesson]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: readme
#
[zl@VM-16-2-centos lesson]$ git reset HEAD readme
Unstaged changes after reset:
M readme
[zl@VM-16-2-centos lesson]$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme
#
no changes added to commit (use "git add" and/or "git commit -a")
[zl@VM-16-2-centos lesson]$ cat readme
hello world
hello git
xxx
[zl@VM-16-2-centos lesson]$ git checkout -- readme
[zl@VM-16-2-centos lesson]$ git status
# On branch master
nothing to commit, working directory clean
[zl@VM-16-2-centos lesson]$ cat readme
hello world
11.2 情况三:已经add,并且也commit了
不要担⼼,我们可以git reset --hard HEAD^回退到上⼀个版本!不过,这是有条件的,就是你还没有把⾃⼰的本地版本库推送到远程。
[zl@VM-16-2-centos lesson]$ vim readme
[zl@VM-16-2-centos lesson]$ git add readme
[zl@VM-16-2-centos lesson]$ git commit -m "modify readme:xxx code"
[master 23501df] modify readme:xxx code
1 file changed, 2 insertions(+)
[zl@VM-16-2-centos lesson]$ git reset --hard HEAD^
HEAD is now at b879e4f modify readme
[zl@VM-16-2-centos lesson]$ git status
# On branch master
nothing to commit, working directory clean
[zl@VM-16-2-centos lesson]$ cat readme
hello world
最后,整体文件撤销的修改总结如下:
十二、删除文件
在Git中,删除也是⼀个修改操作,但直接删除是没有⽤的,反⽽徒增烦恼,git status 命令会⽴刻告诉你哪些⽂件被删除了。此时,⼯作区和版本库就不⼀致了,要删⽂件,⽬前除了要删⼯作区的⽂件,还要清除版本库的⽂件。
⼀般⾛到这⾥,有两种可能
1.确实要从版本库中删除该⽂件
2.不⼩⼼删错了
对第⼆种情况,很明显误删,需要使⽤ git 来进⾏恢复,很简单,我们刚学过(删除也是修改):
对于第⼀种情况,很明显是没有删完,我们只删除了⼯作区的⽂件。这时就需要使⽤git rm 将⽂件从暂存区和⼯作区中删除,并且commit :
[zl@VM-16-2-centos lesson]$ touch file3 file4
[zl@VM-16-2-centos lesson]$ ls
file1 file2 file3 file4 readme
[zl@VM-16-2-centos lesson]$ git add file4
[zl@VM-16-2-centos lesson]$ git rm -f file4
rm 'file4'
[zl@VM-16-2-centos lesson]$ ls
file1 file2 file3 readme
[zl@VM-16-2-centos lesson]$ git status
[zl@VM-16-2-centos lesson]$ git commit -m "delete file4"
现在,文件就从版本库中被删除了。