学习笔记参考自廖雪峰的官方网站
廖雪峰老师的Git文字教程写的真的超级棒!!强烈推荐!!!
欢迎关注我的微信公众号【万能的小江江】
Git简介
安装Git
在Linux上安装Git
可以在命令行输入git
,可以查看系统有没有安装Git
$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
如果没有安装Git,且使用的是Debian和Ubuntu Linux,可以通过下面的指令完成Git的安装
sudo apt-get install git
如果是其他版本的Linux版本,可以直接通过源码安装。先从Git官网下载源码、解压、然后进入对应目录输入下列指令,进行安装:
./config
make
sudo make install
在Windows上安装Git
Windows上安装Git,直接从Git官网下载安装包,按默认选项安装就可以
安装后,在开始菜单找”Git”->”Git Bash”,弹出shell窗口,则说明Git安装成功
安装完成后,设置用户信息,以下是全局配置,针对单个目录进行配置后续将进行补充
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
创建版本库
什么是版本库
版本库又叫仓库,英文名repository,可以简单理解成所有文件都被Git管理起来的目录,每个文件的修改、删除,Git都能跟踪到。可以追踪历史,或者在将来某个时刻可以还原
创建版本库的步骤
1.选一个合适的地方,新建一个空目录
$ mkdir learngit #创建名为learngit的目录
$ cd learngit #进入目录
$ pwd #用于显示当前的目录
/Users/michael/learngit
2.通过git init
命令把这个目录变为Git可以管理的仓库
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/ #初始化仓库完成,并且告诉我们这个仓库是通的
在当前目录下多了一个”.git”的目录,这个目录是Git用来跟踪管理版本库(不能随便更改这个目录里面的文件,该乱了之后就把Git仓库破坏了)
如果没有看到”git”目录,就说明这个目录默认是隐藏的
ls -ah #用这个命令看隐藏的目录
不过不一定在空目录下创建Git仓库,选择已有的目录的也可以
把文件添加到版本库
所有的版本控制系统,只能跟踪文本文件的改动,比如TXT文件、网页、所有的程序代码。版本控制系统可以告诉你在某行添加了什么,在某行删除了什么
但是图片、视频这些二进制文件,虽然也可以用版本控制系统管理,但是没有办法跟踪文件的变化,只能把二进制文件每次的改动串起来。就是只能知道文件大小的变化,但是不能追踪到文件具体内容的变化
注:
微软的Word格式也是二进制文件!
编辑文本文件,推荐用UTF-8编码
不要用Windows自带的记事本编辑文本文件!因为记事本保存UTF-8编码,在文件头会有0xefbbbf这样的字符,可能会在编程的时候出现语法错误。推荐用Notepad++(虽然这个作者反华,别下载反华版本就可)
第一步:编写一个”readme.txt”文件,内容如下:
Git is a version control system.
Git is free software.
这个文件一定要放在”learngit”目录或者其子目录下,因为这是个Git仓库,相当于是这个仓库的解释文件
第二步:用git add
告诉Git,把文件添加到仓库
$ git add readme.txt
第三步:用git commit
告诉Git,把文件提交到仓库
$ git commit -m "wrote a readme file" #""内的内容是对这个版本的解释
[master (root-commit) eaadf4e] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
git commit
命令,-m
后面输入的本次提交的说明,可以输入任意内容,最好是有意义的,这样之后在历史记录里会更方便找到改动记录
git commit
命令执行成功后会告诉你,”1 file change”:1个文件被改动(我们新添加的readme.txt文件;”2 insertions”:插入了两行内容(readme.txt有两行内容)
为什么Git添加文件需要add
,commit
2步
“commit”可以一次提交很多文件,所以可以多次”add”不同的文件
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
疑难解答
Q:输入git add readme.txt
,得到错误:”fatal: not a git repository (or any of the parent directories)”
A:Git命令必须在Git仓库目录内执行(git init
除外),在仓库目录外执行是没有意义的
Q:输入git add readme.txt
,得到错误”fatal: pathspec ‘readme.txt’ did not match any files”
A:添加某个文件时,该文件必须在当前目录下存在,用ls
或者dir
命令查看当前目录的文件,看看文件是否存在,或者是否写错了文件名
小结
总结一下两点内容:
初始化一个Git仓库,使用git init
命令
添加文件到Git仓库,分两步:
- 使用命令
git add <file>
,注意,可反复多次使用,添加多个文件; - 使用命令
git commit -m <message>
,完成
管理版本
基础修改、提交、状态查看
修改“readme.txt”文件
Git is a version control system.
Git is free software.#旧的
Git is a distributed version control system. #新的,distributed分散式
Git is free software.
运行git status
查看结果
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
上面的命令告诉我们”readme.txt”被修改了
运行git diff
命令查看详细修改内容
diff是different的意思,显示的格式也是Unix通用的diff格式
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
用git add
命令,把文件添加到暂存区
$ git add readme.txt
用git status
查看当前仓库状态
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: readme.txt
git status
告诉我们,要被提交的修改包含readme.txt
,之后我们就可以放心提交了
用git commit
提交到版本库
$ git commit -m "add distributed"
[master e475afc] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
用git status
查看当前仓库状态
$ git status
On branch master
nothing to commit, working tree clean
Git提示当前没有需要提交的修改,且工作目录是干净的
小结
- 用
git status
可以随时知道工作区的状态 git status
告诉我们文件有被修改过时,git diff
可以告诉我们具体的修改内容是什么
版本回退
再一次修改readme.txt
文件
Git is a distributed version control system. #旧的
Git is free software.
Git is a distributed version control system.#新的
Git is free software distributed under the GPL.
提交新修改的readme.txt
$ git add readme.txt
$ git commit -m "append GPL"
[master 1094adb] append GPL
1 file changed, 1 insertion(+), 1 deletion(-)
每一次git commit -m
提交都会留下一个记录
用git log
命令查看历史提交日志
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)
Author: Michael Liao
Date: Fri May 18 21:06:15 2018 +0800
append GPL
commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao
Date: Fri May 18 21:03:36 2018 +0800
add distributed
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao
Date: Fri May 18 20:59:18 2018 +0800
wrote a readme file
注:
1.git log
命令显示从最近到最远的提交日志
2.加上--pretty=oneline
参数,可以精简输出信息
3.类似1094...
这样的是commit id(版本号),是通过SHA1计算出来的用16进制表示,有可视化工具可以查看提交的历史事件线,可以通过对应的命令回到相应的版本(回退的时候版本号写前几位就可以了)
4.HEAD代表的是当前版本,HEAD^代表上一个版本,HEAD^^代表上上个版本,向上100个版本,用HEAD~100表示
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
用git reset
回退版本
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
--hard
参数的作用会在后面再说,这时候我们用cat
命令可以查看到readme.txt
回退到了上一个版本
这时候用git log命令查看发现之前的HEAD版本不见了
可以用git reflog
查看之前的命令,找到之前的版本
$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
tips:为什么回退速度这么快?
Git回退版本的速度很快,因为Git内部有个指向当前版本的HEAD
指针,回退版本的时候仅仅是Git把指针指向了不同的版本
小结
HEAD
指向的版本就是当前的版本,使用git reset --hard commit_id
可以在不同版本之间穿梭- 穿梭前,可以用
git log
查看提交历史,看看要回到过去哪个版本 - 穿梭后,可以用
git relog
查看命令历史,看看想回到未来哪个版本
工作区和暂存区
工作区
我们能在文件夹中看到的文件就是工作区中的文件
暂存区和版本库(Repository)
git add
把文件从工作区加到暂存区
git commit
把暂存区的所有内容提交到当前分支(-m的意思是提交到master分支??)
需要提交的文件都放到暂存区,之后一次性提交到版本库
Practice
对readme.txt进行修改,再在工作区新增LICENSE
文件
Git is a distributed version control system.#旧的
Git is free software distributed under the GPL.
Git is a distributed version control system.#新的
Git is free software distributed under the GPL.
Git has a mutable index called stage.
用git status
查看文件状态
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: readme.txt
Untracked files:
(use "git add ..." to include in what will be committed)
LICENSE
no changes added to commit (use "git add" and/or "git commit -a")
可以看到提示我们readme.txt
被修改了,LICENSE
是Untracked状态(没被添加)
添加文件到版本库
$ git add readme.txt LICENSE
$ git commit -m "add LICENSE"
用git status
查看文件状态
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: LICENSE
modified: readme.txt
小结
弄清楚暂存区的概念是十分重要的,弄清楚暂存区是做什么的,就弄明白了Git的很多操作的原因是什么
管理修改
第一次修改 -> git add
-> 第二次修改 -> git add
-> git commit
小结
了解Git是如何跟踪修改的,如果不用git add
到暂存区,就不会加入到commit
中
撤销修改
丢弃工作区的修改–修改未存到暂存区,或存暂存后又修改
git checkout -- file #丢弃工作区的修改,回到暂存区状态 --很重要,不然就会变成切换到另外一个分支的命令
丢弃暂存区的修改–修改已保存到暂存区,放回工作区
git reset HEAD #把暂存区的修改撤销,重新放回工作区,HEAD表示最新的版本
丢弃版本库的修改–版本回退
版本回退适用于还没推送到远程版本库的情况
小结
- 丢弃工作区修改,用命令
git checkout -- file
丢弃 - 丢弃暂存区修改,先用命令
git reset HEAD <file>
放回工作区,再用命令git checkout -- file
丢弃(和上一步一样) - 丢弃版本库修改,用版本回退的方法
git reset --hard commit_id
删除文件
在Git中,删除也是一个修改的操作
方式1:git rm
命令
$ git rm test.txt
rm 'test.txt'
方式2:git commit
命令
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
删错了撤销:git checkout
命令
$ git checkout -- test.txt
实际上是用版本库里的版本替换工作区的版本
但是只能恢复最后一次提交的内容
小结
直接用rm
命令删除文件会导致工作区和版本库不一致
Git中正确地删除文件有两种方式,一种是git rm
命令,还有一种是用git commit
如果不小心误删了,可以用git checkout
命令恢复,但是只能回复最后一次的版本
远程仓库
连接到Github
创建SSH key
$ ssh-keygen -t rsa -C "[email protected]" #一路回车设置即可
创建好SSH Key之后,可以在Windows用户的主目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个文件就是SSH Key的密钥对,id_rsa
是私钥,不能被泄露出去,id_rsa.pub
是公钥,可以放心告诉别人
登录Github
打开Account settings
的SSH Keys页面,点Add SSH Key
,title
任意填写,在Key文本框中粘贴id_rsa.pub
的内容。点Add Key
,就看添加了
注:
Git支持添加多个Key,可以多个终端的Key都添加到Github,就可以多终端推送了
不想被别人看到自己的Git的库的方法,一个 是把仓库设置为私有库,另外一个是自建服务器
添加远程仓库
Create a new repo
登录Github,输入相关信息,新建仓库
从本地推送到Github
连接到Github仓库
新建好的仓库是空的,在本地执行下列代码,可以把本地仓库的内容连接到Github仓库
$ git remote add origin [email protected]:michaelliao/learngit.git #michaelliao是自己的账户名,learngit是仓库名
远程库的名字是origin
,是Git的默认叫法,但是也可以改成别的,origin一看就知道是远程库
推送到Github仓库
把本地库推送到远程,用git push
命令,实际上是把当前分支master
推送到远程
由于远程库是空的,所以第一次推送到master
分支时,加上了-u
参数。这样,Git不仅会把本地的master
分支的内容推送到远程的master
分支,还会把两个库关联起来,以后推送或者拉去的时候可以简化命令
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
推送成功后,就可以立刻在Github页面中看到远程库的内容已经和本地一模一样了
以后,只要本地做了修改,就可以通过厦门下面的命令,把本地master
分支推送到Github。从此,拥有真正的分布式版本库
$ git push origin master
SSH警告
第一次用Git的clone
或者push命令连接到Github的时候,会得到一个警告:
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
这是因为Git使用SSH连接,SSH连接第一次验证Github服务器的Key的时候,需要我们曲儿Github服务器的Key的指纹信息是否真正来自Github服务器,输入yes即可
Git会输出一个警告,告诉我们已经把Github的Key添加到本机的一个信任列表了:
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
注:Github的公钥指纹可在此处对比查看指纹信息是否正确
删除远程库
添加的时候地址写错了,或者想要删除远程库,可以用git remote rm <name>
命令。
使用前,先用git remote -v
命令查看远程库的信息
$ git remote -v
origin [email protected]:michaelliao/learn-git.git (fetch)
origin [email protected]:michaelliao/learn-git.git (push)
之后,根据名字删除,比如删除orgin
$ git remote rm origin
注:
此处的”删除“只是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库并没有任何改动,如果真要删除远程库,需要登陆到Github,在后台页面找到删除按钮再删除
小结
- 要关联远程仓库,用
git remote add origin git@server-name:path/repo-name.git
- 关联的时候必须要给远程仓库指定一个名字,
origin
是习惯命名 - 关联后,第一次用
git push -u origin master
命令推送所有master
分支内容 - 每次本地提交后,有必要的话,可以用
git push origin master
推送最新修改
分支管理
分支可以理解为科幻电影里面的平行宇宙,两个平行宇宙互不干扰
分支在实际工作中可以单独开发某个功能,而不影响整个项目的整体进度,且Git创建、切换、删除分支的速度很快
创建与合并分支
每一次的提交,Git都会把它们串成一条时间线,这条时间线就是一个分支。之前的学习中,只有一条时间线,也就只有一个分支:主分支即master
分支。HEAD严格来说不是指向提交,而是指向master
,master
才是指向提交,HEAD指向的是当前分支