Git应该是一个程序员必备的技能,但居然有人不会。最近在准备实习,在对自己的技术进行查漏补缺(女娲补天),有不少同学也跟我一样。因此前几天,一个同学问我你会Github吗?我说会啊!他用敬佩的眼神痴痴地看着我,我淡定的说其实挺简单的。
Git作为必备技能,为什么会有人不知道呢?我想大概这是个工具吧,所以学校里也不教,大家也就不学。想学的呢,网上看了一些教程,又非常的晦涩难懂,其实入门还是很简单的(我也只会一些基本操作,目前够用),于是今天我就翻开我的笔记本,把之前学习Git做的一点点笔记分享给大家。
Git是什么?
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.(官网复制来的)
Git是一个开源免费的版本控制器,不管是大项目还是小项目,都可以又快又准的把你治的服服贴贴。
这是linux之父的一周还是两周的一个作品,因为Linux内核开源后参与的人非常多,人工的合并代码很麻烦且容易出错,当时已有的版本控制库还想跟linux收保护费,于是就有了Git,具体来历自己去搜搜吧,我就不复制了。
那么版本控制是什么意思呢??
为什么我们平时用不到呢,因为我们在学校里写的代码,一共就一个版本,一般都是独立完成,项目还很小,写完以后作用就不大了。
但是大项目就不一样了,有许许多多的版本。比如说绝地求生
- 垃圾服务器天天维护,游戏天天出Bug,就得天天更新,所以把历史版本,变动记录下来是有意义的,万一哪天改完了发现游戏都进不去了,还可以切换到昨天的版本让玩家玩玩Bug版本。
- 一部分程序员得研究怎么防外挂,一部分要研究怎么出新地图,新玩法,那么两部分人怎么合作呢??
Git安装
Linux下:
sudo apt-get install git
Windows下:
安装之后配置一下个人信息:
git config --global user.name "wuyanzu"
git config --global user.email "xxxx@xx.xxx"
理解三个区域
理解Git如何工作首先要弄明白Git的三个区域,相当于三个不同的目录
- 工作目录
- 暂存区
- Git仓库
工作目录
工作目录就是我们保存代码的那个目录
暂存区
一个介于工作目录和Git仓库之间的目录,就当临时仓库吧
Git仓库
保存每个版本的仓库,每一个版本都完整保存,内部有一个HEAD指针
一般的工作流程
在工作区写代码,修改代码
将修改的代码放入暂存区
将暂存区的改动提交到Git仓库
一个完整流程遇到的命令介绍
Git是有图形操作界面的,但是一般都学命令操作,命令操作学会了图形自然而然就会了。
首先我们创建一个目录,用于放代码,并初始化Git仓库。
mkdir project_1
cd project_1
git init
# output: 初始化空的 Git 仓库于/home/chenfeikun/project_1/.git/
git init
的作用是初始化,告诉Git这个目录以后要被控制,被记录,现在目录里会多出一个.git
文件夹,是一个隐藏文件,这个文件夹以后会自动记录各种操作,不要动它就行。
然后在目录里开始创作,写了一个README和一个hello.py
chenfeikun@cfk-ubuntu:~/project_1$ ls
hello.py README.md
执行git status查看文件变动情况
chenfeikun@cfk-ubuntu:~/project_1$ git status
位于分支 master
初始提交
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
README.md
hello.py
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
git发现我们添加了两个文件,还没有被追踪,可以用git add
追踪。追踪呢就是让git一直注意着这个文件,任何改动都会被发现,git add
就把文件放入我们之前提到的暂存区。
执行git add <file_name>或git add *
chenfeikun@cfk-ubuntu:~/project_1$ git add README.md hello.py
这个没有提示,所以我们可以再用git status
来查看一下现在的状态。
位于分支 master
初始提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: README.md
新文件: hello.py
可以看到这两个文件已经提交到暂存区了,如果突然发现hello.py需要修改,或者是机密文件不能传出去,那么可以按提示里的命令取消暂存,或者修改hello.py后重新执行git add
。
一切OK后就需要提交到Git仓库了,提交到这里面就算保存了第一个版本了,后续的提交就算是新的版本了。
使用git commit -m 'xxx'提交至Git仓库
chenfeikun@cfk-ubuntu:~/project_1$ git commit -m 'add two new file'
[master (根提交) 7319582] add two new file
2 files changed, 5 insertions(+)
create mode 100644 README.md
create mode 100644 hello.py
-m的作用就是在提交的时候附加一个提交的说明,这样以后找历史版本会方便一点, xxx就是附加的内容。
仔细看提交之后的输出,[]里有一串字符串7319582(不全是数字),这里显示的其实只是前面的一部分,完整的还很长。这个字符串是标识每一次提交的,也就是每一次提交都会生成一个唯一的字符串,在同一个仓库里这个字符串只会出现一次。这个字符串可以用于以后切换版本,只需要输入前面几位就行,不需要补全。记不住也没关系,有命令可以查询这个唯一标识。
回到过去
上面我们介绍了从工作目录到暂存区再到Git仓库的过程,那么如何反过来呢?
从Git仓库到暂存区
git reset --mixed HEAD
git reset --soft HEAD~
git reset --hard HEAD~~
git reset HEAD~3
git reset 7319582(指定版本的唯一标识串)
HEAD在Git仓库中指向的是最新版本,HEAD~是最新版本的上一个版本,HEAD~~是上两个版本,但是总不能写很多个~~~~~~,所以可以写成HEAD~N,N就是~的个数。
git reset就是把Git仓库中的版本,覆盖暂存区的版本,甚至覆盖工作区的版本(有危险的,你修改的内容可能全部丢失)。
mixed,soft,hard三个参数就是决定如何覆盖的,其中mixed是默认选项,也就是不输入参数时的选项。
用git reset HEAD~
举例说明三种参数各自情况
soft:移动HEAD指针指向上一个版本,暂存区,工作区无变化
mixed:移动HEAD指针指向上一个版本,并用HEAD当前指向的版本覆盖暂存区,工作区域不变(注意这时候使用git status会指出工作区变化了,那是因为工作区与最新的暂存区不一样了,本质是暂存区改变了)
hard:移动HEAD指针指向上一个版本,并用HEAD当前指向的版本覆盖暂存区和工作区(危险,工作区修改会丢失)
查询版本ID号
每一次提交到Git仓库都有一串哈希值,就叫它ID号吧。怎么查询呢,有两个命令git log
和git relog
。
假设提交了四次,Git仓库内是这样的:A->B->C->D,HEAD->C。
因为HEAD指向了倒数第二次提交的C版本,那么使用git log
只会显示出C之前的所有提交,使用git reflog
才会把所有的提交都显示出来。
HEAD指向C: git reset a9a00d
reflog:
chenfeikun@cfk-ubuntu:~/project_1$ git reflog
a9a00d0 HEAD@{0}: reset: moving to a9a00d
d431515 HEAD@{1}: commit: commit D
a9a00d0 HEAD@{2}: commit: commit C
6890baf HEAD@{3}: commit: commit B
7319582 HEAD@{4}: commit (initial): add two new file
log:
chenfeikun@cfk-ubuntu:~/project_1$ git log
commit a9a00d07fb3a07bb880d7c9835dcfcd2c15ade04
Author: cfk1996 <297770449@qq.com>
Date: Fri Mar 2 16:17:11 2018 +0800
commit C
commit 6890baf18c283c60e9f29df4be7948fc248e91f0
Author: cfk1996 <297770449@qq.com>
Date: Fri Mar 2 16:16:52 2018 +0800
commit B
commit 731958281a1d63b552f90367dc8d68c1a17c632d
Author: cfk1996 <297770449@qq.com>
Date: Fri Mar 2 15:42:48 2018 +0800
add two new file
从暂存区到工作区
上面一小节的命令以及可以覆盖工作区了,但是那些都是Git仓库中的版本。有时候我们git add
后,在还没有git commit
之前,又在工作目录中修改了代码,觉得改的不好,想切换到没改之前的样貌,就可以把暂存区的内容复制到工作区。
git checkout --<filename>
总结一下三个目录
- 工作目录--
git add
-->暂存区--git commit
-->Git仓库 - 工作目录<--
git checkout
--暂存区<--git reset
--Git仓库
git分支
Git另外一个重要的功能就是分支了,分支可以多人合作开发以及开发新功能的需求。我目前没怎么用到过,所以就只是简单的介绍一下,主要还是搞懂三个分区的概念,其次就是弄懂Git仓库里各个版本是用指针连在一起的。所以分支就是在Git仓库中某个版本A复制一份A’,然后创建一个A->A'的指针,就可以互不干扰的在两处地发进行开发。
创建分支
git branch branch-name # 无提示
切换分支
git checkout branch-name
这个命令进行的操作就是将HEAD指针指向分支,且覆盖工作区文件。(切回原来的分支,还会覆盖一次,所以不丢失)
合并分支
git merge branch-name
在进入一个分支后,可以用这个命令与另外一个分支合并。但是合并可能失败,也就是发生冲突。即两个分支中存在同名文件,但是文件内容不一样,Git就不知道保留哪一个文件,这就需要我们手动修改冲突文件后再合并。
删除分支
git branch -d branch-name
查看修改细节
git diff # 比较工作区和暂存区
git diff id_1 id_2 # 比较两个历史版本
git diff id # 比较工作区与这个版本
git diff --cached id # 比较暂存区与这个版本
这个命令是不难,但是会输出很多的内容,内容就是两个版本比较后的差异,看起来比较麻烦。
Github
Github就是一个远程仓库,可以把我们刚才提到的Git仓库在他们那保存一份。这样的好处就是,不容易丢失,可以让更多的人参与进来。
所以会了Git以后Github的使用也就会了,它就是帮我们保存的,所以平时的操作就是两个:
把我的仓库放过去
git push
把远程的仓库拿过来
git clone