本人拜读了廖雪峰老师关于Git的讲述后整理所得

1.创建版本库:

版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

找一个地方创建一个目录

$ mkdir GitStudy
$ cd GitStudy/

$ pwd
/d/GitStudy

通过git init命令把这个目录变成Git可以管理的仓库:

$ git init
Initialized empty Git repository in D:/GitStudy/.git/

Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),细心的读者可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -al命令就可以看见。

$ ls -al
total
drwxr-xr-x chao03.li 七月 : ./
drwxr-xr-x chao03.li 七月 : ../
drwxr-xr-x chao03.li 七月 : .git/

然后创建一个测试文件

$ touch readme.txt

$ vim readme.txt

$ cat readme.txt
I will study git in this txt

查看工作区中的文件状态【untracked files】未被标记的、未被跟踪的文件就是在工作区没有add到暂存区

$ git status
On branch master Initial commit Untracked files:
(use "git add <file>..." to include in what will be committed) readme.txt nothing added to commit but untracked files present (use "git add" to track)

用命令git add告诉Git,把文件添加到仓库:

$ git add readme.txt

$ git status
On branch master Initial commit Changes to be committed:
(use "git rm --cached <file>..." to unstage) new file: readme.txt

用命令git commit告诉Git,把文件提交到仓库:

git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。

$ git commit -m "first time to commit readme.txt"
[master (root-commit) bb86898] first time to commit readme.txt
file changed, insertion(+)
create mode readme.txt

初始化一个Git仓库,使用git init命令。

添加文件到Git仓库,分两步:

  • 第一步,使用命令git add <file>,注意,可反复多次使用,添加多个文件;

  • 第二步,使用命令git commit,完成。

2.版本状态及文件对比:

修改readme.txt

$ vi readme.txt

$ cat readme.txt
I will study git in this txt
Git is not too hard

git status命令可以让我们时刻掌握仓库当前的状态,下面的命令告诉我们,readme.txt被修改过了,但还没有准备提交的修改。

$ 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.txt no changes added to commit (use "git add" and/or "git commit -a")

Git告诉我们readme.txt被修改了,通过git diff命令看具体修改了什么内容

$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index e2905ad..14c34f7
--- a/readme.txt
+++ b/readme.txt
@@ - +, @@
I will study git in this txt
+Git is not too hard

将修改过后的文件提交到Git同样分为两步:add+commit

$ git add readme.txt

$ git commit -m "second time to add a row"
[master f609340] second time to add a row
file changed, insertion(+)

再用git status命令看看仓库的当前状态,工作目录是干净(working directory clean)的。

$ git status
On branch master
nothing to commit, working tree clean
  • 要随时掌握工作区的状态,使用git status命令。

  • 如果git status告诉你有文件被修改过,用git diff可以查看修改内容。

3.版本回退:

在readme.txt文件中新添加一行

$ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder

然后将其提交,像这样,你不断对文件进行修改,然后不断提交修改到版本库里,就好比玩RPG游戏时,每通过一关就会自动把游戏状态存盘,如果某一关没过去,你还可以选择读取前一关的状态。有些时候,在打Boss之前,你会手动存盘,以便万一打Boss失败了,可以从最近的地方重新开始。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。

现在,我们回顾一下readme.txt文件一共有几个版本被提交到Git仓库里了:git log readme.txt

$ git log readme.txt
commit 31bd1cc7f2ddd14dadd02a314009a4c50924e9a0 (HEAD -> master)
Author: chao03.li <chao03.li@phicomm.com>
Date: Sat Jul :: + add row god is coder commit f609340795ca1b078a473368d3b815b88a2fc0be
Author: chao03.li <chao03.li@phicomm.com>
Date: Sat Jul :: + second time to add a row commit bb86898e9b497f7dea9fa653e0c66d4b8ee7ffa2
Author: chao03.li <chao03.li@phicomm.com>
Date: Sat Jul :: + first time to commit readme.txt

git log命令显示从最近到最远的提交日志,我们可以看到3次提交

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

$ git log --pretty=oneline
31bd1cc7f2ddd14dadd02a314009a4c50924e9a0 (HEAD -> master) add row god is coder
f609340795ca1b078a473368d3b815b88a2fc0be second time to add a row
bb86898e9b497f7dea9fa653e0c66d4b8ee7ffa2 first time to commit readme.txt

你看到的一大串类似3628164...882e1e0的是commit id(版本号),和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id和我的肯定不一样,以你自己的为准。为什么commit id需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。

把readme.txt回退到上一个版本:

Git用HEAD表示当前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

$ git reset --hard HEAD^
HEAD is now at f609340 second time to add a row $ cat readme.txt
I will study git in this txt
Git is not too hard

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL

改为指向add distributed

然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。

我们用git log再看看现在版本库的状态你会发现最新的那个版本God is a coder已经看不到了!

$ git log
commit f609340795ca1b078a473368d3b815b88a2fc0be (HEAD -> master)
Author: chao03.li <chao03.li@phicomm.com>
Date: Sat Jul :: + second time to add a row commit bb86898e9b497f7dea9fa653e0c66d4b8ee7ffa2
Author: chao03.li <chao03.li@phicomm.com>
Date: Sat Jul :: + first time to commit readme.txt

如果想回去之前的那个版本,使用git reflog 找到之前提交的那个commit id是31bd1cc...,于是就可以指定回到未来的某个版本:

$ git reflog
f609340 (HEAD -> master) HEAD@{}: reset: moving to HEAD^
31bd1cc HEAD@{}: commit: add row god is coder
f609340 (HEAD -> master) HEAD@{}: commit: second time to add a row
bb86898 HEAD@{}: commit (initial): first time to commit readme.txt $ git reset --hard 31bd1cc
HEAD is now at 31bd1cc add row god is coder $ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id

  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

4.工作区和暂存区:

Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。

工作区(Working Directory)

就是你在电脑里能看到的目录,比如我的GitStudy文件夹就是一个工作区:

版本库(Repository)

工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

示例修改readme.txt新增LICENSE:

$ vi readme.txt

$ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man $ touch LICENSE $ cat LICENSE
sad

查看状态

$ 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.txt Untracked files:
(use "git add <file>..." to include in what will be committed) LICENSE no changes added to commit (use "git add" and/or "git commit -a")

Git非常清楚地告诉我们,readme.txt被修改了,而LICENSE还从来没有被添加过,所以它的状态是Untracked

现在,使用两次命令git add,把readme.txtLICENSE都添加后,用git status再查看一下:

$ git add readme.txt

$ git add LICENSE

再一次查看文件状态:

$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage) new file: LICENSE
modified: readme.txt

现在,暂存区的状态就变成这样了:

所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。

$ git commit -m "test stage"
[master afcd497] test stage
files changed, insertions(+)
create mode LICENSE

一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:

$ git status
On branch master
nothing to commit, working tree clean

现在版本库变成了这样,暂存区就没有任何内容了:

5.管理修改:

修改readme.txt文件,add到暂存区,然后在进行修改,然后在进行commit操作,只将第一次修改的内容进行了提交。

$ git add readme.txt

$ vi readme.txt

$ git commit -m "two update one add one commit"
[master 155d578] two update one add one commit
file changed, insertion(+) $ 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.txt no changes added to commit (use "git add" and/or "git commit -a")

第二次的修改没有被提交。

第一次修改 -> git add -> 第二次修改 -> git commit

你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。

提交后,用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别:

$ git diff -- readme.txt
diff --git a/readme.txt b/readme.txt
index a0f2585..e240599
--- a/readme.txt
+++ b/readme.txt
@@ -, +, @@ Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
+: writen

Git是如何跟踪修改的?每次修改,如果不add到暂存区,那就不会加入到commit中。

6.撤销修改:

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。

修改完一个文件--》发现不对劲--》撤销修改

$ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen
We will fuck! $ 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.txt no changes added to commit (use "git add" and/or "git commit -a") $ git checkout -- readme.txt $ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen $ git status
On branch master
nothing to commit, working tree clean

修改完一个文件--》add到暂存区--》发现有问题--》撤销更改(checkout不能修复这种情况)

$ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen
Fight Now $ git add readme.txt $ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage) modified: readme.txt

修改完一个文件--》add到暂存区--》--》继续对文件进行修改--》发现有问题--》撤销更改

$ vi readme.txt

$ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen
Fight Now
I will buy macbook
it cost $990.00 $ git checkout -- readme.txt $ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen
Fight Now
I will buy macbook

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。

修改完一个文件--》add到暂存区--》发现有问题--》撤销更改(reset可以修复这种情况)

$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage) modified: readme.txt $ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt $ 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.txt $ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen
Fight Now
I will buy macbook

还记得如何丢弃工作区的修改吗?

$ git checkout -- readme.txt

$ cat readme.txt
I will study git in this txt
Git is not too hard
God is a coder
LiaoXueFeng is a subalasi man
--
: writen
Fight Now

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。

7.删除修改:

一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:

这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:

--》一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit

--》另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

先说第二种:

$ vi test.txt

$ git add test.txt

$ git commit -m "test rm"
[master 21aa1a8] test rm
file changed, insertion(+)
create mode test.txt $ git status
On branch master
nothing to commit, working tree clean $ rm -rf test.txt $ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory) deleted: test.txt no changes added to commit (use "git add" and/or "git commit -a") $ ls
LICENSE readme.txt $ git checkout -- test.txt $ ls
LICENSE readme.txt test.txt $ git status
On branch master
nothing to commit, working tree clean

第一种情况:

$ rm -rf test.txt

$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory) deleted: test.txt no changes added to commit (use "git add" and/or "git commit -a") $ git rm test.txt
rm 'test.txt' $ git commit -m "remove test.txt"
[master 929d205] remove test.txt
file changed, deletion(-)
delete mode test.txt

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容

Git-基本操作(同SVN)的更多相关文章

  1. Git学习系列之Git基本操作拉取项目(图文详解)

    前面博客 Git学习系列之Git基本操作推送项目(图文详解) 当然,如果多人协作,或者多个客户端进行修改,那么我们还要拉取(Pull ... )别人推送到在线仓库的内容下来. 大神们是不推荐使用 pu ...

  2. Git学习系列之Git基本操作克隆项目(图文详解)

    不多说,直接上干货! 想必,能进来看我写的这篇博文的朋友,肯定是了解过. 比如SVN的操作吧,最常见的是 检出(Check out ...), 更新 (Update ...), 以及 提交(Commi ...

  3. 【转载】git命令和svn的对比

    首先,要明确的是,git和svn是完全不同的两种管理方式.他们的命令不是完全对等的. 下面只是一些相似方法的参考,而已. 参考 http://blog.csdn.net/chen198746/arti ...

  4. Git基本操作和GtHub 特殊技巧

    <GitHub 入门与实践> 笔记 了解GitHub Git 和 GitHub 的区别 在Git中,开发者将源代码存入名为"Git仓库"的资料库中,并加以使用.而Git ...

  5. git实践:对比svn

    先前只用过svn,自然也没有去对比什么好坏,亲自上手之后发现svn和git实在是有很多不同 svn优点: 学习成本对比非常低 服务器公司统一控制管理 安全机制, 不会每个人都拷贝一份, 可以对组员限制 ...

  6. Git学习系列之Git基本操作推送项目(图文详解)

    前面博客 Git学习系列之Git基本操作提交项目(图文详解) 如果完成到一定程度,那么可以推送到远端在线仓库. 推送之前,请确保你已经设置了全局的 user.name 和 user.email, 如果 ...

  7. Git学习系列之Git基本操作提交项目(图文详解)

    前面博客 Git学习系列之Git基本操作克隆项目(图文详解) 然后可以 cd 切换到 LispGentleIntro 目录, 新增或者修改某些文件.这里只是模拟一下操作, 实际情况可能是 使用 Ecl ...

  8. Git迁移 从SVN到Git

    Migrating from SVN to Git 首先我们需要在Stach或者GitHub上新建一个Repository, 拿到它的URL. 接下来参照如下步骤 : At first we shou ...

  9. Git-Runoob:Git 基本操作

    ylbtech-Git-Runoob:Git 基本操作 1.返回顶部 1. Git 基本操作 Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比.本章将对有关创建与提交你的项目快照的命令作 ...

  10. 学习如何运用GitHub网站+出现的问题+Git基本操作总结

    首先介绍一下GitHub网站: github是一个基于git的代码托管平台. GitHub 拥有一个非常鼓励合作的社区氛围.这一方面源于 GitHub 的付费模式:私有项目需要付费,而公共项目完全免费 ...

随机推荐

  1. Nucleus PLUS的启动、执行线程和中断处理

    nucleus系统是实时嵌入式操作系统,具有实时.任务抢先.多任务内核,当中95%的代码由C语言写成,极易移植.开放的源代码使得配置和裁剪方便,再加上体积小(所有二进制映像可仅20K).响应高速等特性 ...

  2. python 发送email

    pyton smtplib发送邮件 在邮件中设置并获取到 smtp域名 在脚本中执行命名,收件人可以是 多个,在列表中 import smtplib from email.mime.text impo ...

  3. openssl之EVP系列之8---EVP_Digest系列函数具体解释

    openssl之EVP系列之8---EVP_Digest系列函数具体解释     ---依据openssl doc/crypto/EVP_DigestInit.pod翻译和自己的理解写成     (作 ...

  4. 编程之美 set 19 连连看游戏设计

    题目 1. 怎么用简单的计算机模型来描述这个问题 ? 2. 怎么判断两个图像是否能相消 3. 怎么求出相同图形之间的最短距离(转弯数最少)? 4. 怎么确定目前处于死锁状态? 如何设计算法来解除死锁? ...

  5. PagerAdapter 普通写法

    1,viewPagre的普通写法 public ImagePagerAdapter(Context context, List<Photo> imgList) { this.mContex ...

  6. ListView中的方法

    getCount(); getItem(); getItemId(); getView(); getViewCountType();

  7. webpack配置(一)

    这里再配置的时候走了些弯路,现在,把配置前的准备工作做好很重要: 首先,安装node.js,当然,npm也就有了: 其次,安装xampp,主要是为了配置Apache: 安装好后,xampp---htd ...

  8. 【BZOJ2973】石头游戏 矩阵乘法

    [BZOJ2973]石头游戏 Description 石头游戏的规则是这样的. 石头游戏在一个n行m列的方格阵上进行.每个格子对应了一个编号在0~9之间的操作序列. 操作序列是一个长度不超过6且循环执 ...

  9. [SharePoint 2010]Sandboxed Solution (沙箱解決方案)

    現有的SharePoint 2007系統中,我們如果要安裝客製化的程式碼到系統中,我們必須製作一個解決方案包裝檔(Solution Package),然後在系統的中央管理後台中,真對整個伺服器農場Fa ...

  10. 高性能流媒体服务器EasyDSS前端重构(一)-从零开始搭建 webpack + vue + AdminLTE 多页面脚手架

    本文围绕着实现EasyDSS高性能流媒体服务器的前端框架来展开的,具体EasyDSS的相关信息可在:www.easydss.com 找到! EasyDSS 高性能流媒体服务器前端架构概述 EasyDS ...