Git系统总结学习(一)

基本概念

使用Git时,对于任何一个文件,在 Git 内都只有三种状态:已提交 (committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存 的清单中。

配置Git

你可以使用git config来配置Git。你可以从三个不同的地方来更改Git的环境变量。

使用git config --system

git config --system是针对系统中对所有用户都普遍适用的配置。个人认为对于本地环境下的个人用户,使用场景并没有那么多。

使用git config --global

git config --global是针对用户目录下的配置,该配置只适用于该用户。我们可以通过该命令来设置自己本地环境的相关信息。

当前项目的 git 目录中的配置文件

我们知道,在自己项目的根目录下有一个隐藏的.git目录,我们可以针对该项目进行单独的配置。在这里的git配置可以覆盖global和system的配置信息。

举例:配置你个人的用户名称和电子邮件地址

查看原来的设置:

~/Desktop » git config --global user.name                                                           liuxingxing@liuxingxingdeMacBook-Pro
刘星星
~/Desktop » git config --global  user.email                                                         liuxingxing@liuxingxingdeMacBook-Pro
lxxwork0827@163.com

更改配置:

~/Desktop » git config --global user.name "liuxingxing"
~/Desktop » git config --global  user.email "smileasy@foxmail.com"

如果用了 –global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默 认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 –global 选项重 新配置即可,新的设定保存在当前项目的 .git/config 文件里。

更改其他配置

文本编辑器:

~/Desktop » git config --global core.editor emacs

差异分析工具:

~/Desktop » git config --global merge.tool vimdiff

查看配置信息

~/Desktop » git config --list

Git基础

从现有仓库克隆

$ git clone git://github.com/liuxingxing.git

这会在当前目录下创建一个名为 “liuxingxing” 的目录,其中内含一个 .git 的目录,并从同步后的仓库中拉出所有的数据,取出最新版本的文件拷贝。如果希望在克隆的时候,自己定义要新建的项目目录名称为”smileay”,可以在上面的 命令最后指定:

$ git clone git://github.com/liuxingxing.git  smileay

从当前目录初始化

现在我们有个项目,名叫gitDemo,里面有个文件叫做README.md.现在我们希望对该项目使用 Git 管理,只需到此项目所在的目录,执行:

git init

如果当前目录下的文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟 踪,然后提交:

$ git add README.md
$ git commit -m 'initial project version'

已跟踪或未跟踪

请记住,工作目录下面的所有文件都不外乎这两种状态:已跟踪或未跟踪。已跟踪的文件是指本来就被纳入 版本控制管理的文件,在上次快照中有它们的记录,工作一段时间后,它们的状态可能是未更新,已修改或者 已放入暂存区。而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存区域。 初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪文件,且状态为未修改。在编辑过某些文件之后,Git将这些文件标为已修改。我们逐步把这些修改过的文件放到暂存区域,然后等 最后一次性提交暂存区域的所有文件更新,如此重复。

检查当前文件状态

要确定哪些文件当前处于什么状态,可以用 git status 命令:

~/Desktop/gitDemo(master) » git status                                                           
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

这说明现在的工作目录相当干净。换句话说,当前没有任何跟踪着的文件,也没有任何文件在上次提交后 更改过。此外,上面的信息还表明,当前目录下没有出现任何处于未跟踪的新文件,否则 Git 会在这里列出来。最后,该命令还显示了当前所在的分支是 master,这是默认的分支名称,实际是可以修改.

跟踪新文件

现在,我们将一个叫learn.png 文件添加到项目中.然后再运行git status查看状态:
使用命令 git add 开始跟踪一个新文件。所以,要跟踪 learn.png 文件,可以运行:

~/Desktop/gitDemo(master) » git status                                                              
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    learn.png

nothing added to commit but untracked files present (use "git add" to track)

可以看到,learn.png被标记为Untracked files.Untracked files表示Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它这么做,因而不用担心把临时文件什么的也归入版本管理。git提示你可以通过git add<文件名>来将其纳入版本管理.

我们使用命令 git add 开始跟踪learn.png文件:

~/Desktop/gitDemo(master*) » git add learn.png                                                      liuxingxing@liuxingxingdeMacBook-Pro
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   learn.png

可以看到learn.png被添加到 “Changes to be committed”下面了.我们需要知道,在 “Changes to be committed” 这行下面的,就说明是已暂存状态。如果此时提交,那么该文件此 时此刻的版本将被留存在历史记录中。git add 后可以接要跟踪的文件或目录的路径。如果是目录的话,就说明要递归跟踪所 有该目录下的文件。

暂存已修改文件

现在我们将README.md文件里面的内容做做修改以用来测试,然后再次运行 status 命令:

-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   learn.png

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.md

------------------------------------------

文件 README.md 出现在 “Changes not staged for commit” 这行下面,说明已跟踪文件的内容发生了变 化,但还没有放到暂存区。要暂存这次更新,需要运行 git add 命令(这是个多功能命令,根据目标文件的状 态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时 把有冲突的文件标记为已解决状态等)。现在让我们运行 git add 将 README.md 放到暂存区,然后再看 看 git status 的输出:

-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git add README.md                                                      liuxingxing@liuxingxingdeMacBook-Pro
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README.md
    new file:   learn.png

-------------------------------------------------------------------------------------------------------------------------------------

现在两个文件都已暂存,下次提交时就会一并记录到仓库。

假设此时,你想要在 README.md 里再加条注释,重新编辑存盘后,准备好提交。不过且慢,再运行 git status 看看:

-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README.md
    new file:   learn.png

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.md

----------------------------------------------------------------------------------------------

你会发现 README.md文件出现了两次!一次算未暂存,一次算已暂存,这有点让人费解.实际上 Git 只不过暂存了你运行 git add命令时的版本,如果现在提交,那么提交的是添加注释前的版本,而非当前工作目录中的版本。所以,运行了 git add 之后又作了修订的文件,需要重新运行 git add 把最新版本重新暂存起来.

忽略某些文件

般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生 成的文件,像是日志或者编译过程中创建的等等。我们可以创建一个名为 .gitignore 的文件,列出要忽略的 文件模式.如果自己并不十分确定究竟要忽略哪些文件,可以在GitHub上找到对应项目类型的.gitignore文件.当然,你也可以自己创建这个.gitignore文件:

# 此为注释 – 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

查看已暂存和未暂存的更新

假如再次修改 README 文件后先别暂存,然运行 status 命令,会看到:

~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README.md
    new file:   learn.png

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.md

-------------------------------------------------------------

要查看尚未暂存的文件更新了哪些部分,不加参数直接输入 git diff:

diff --git a/README.md b/README.md
index 3673bf4..7cf08ef 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@


-德玛洗牙
+德玛西亚
(END)

此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内 容。请注意,单单 git diff不过是显示还没有暂存起来的改动,而不是这次工作和上次提交之间的差异。所以有 时候你一下子暂存了所有更新过的文件后,运行 git diff 后却什么也没有,就是这个原因。若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff –cached 命令或者(git diff –staged命令).

提交更新

现在的暂存区域已经准备妥当可以提交了。在此之前,请一定要确认还有什么修改过的或新建的文件还没有 git add 过,否则提交的时候不会记录这些还没暂存起来的变化。所以,每次准备提交前,先用 git status 看 下,是不是都已暂存起来了,然后再运行提交命令:

~/Desktop/gitDemo(master*) » git commit  -m '我是提交注释'                                          liuxingxing@liuxingxingdeMacBook-Pro
[master bef8ce0] 我是提交注释
 2 files changed, 3 insertions(+), 2 deletions(-)
 create mode 100644 learn.png
---------------------------------

好,现在你已经创建了第一个提交!可以看到,提交后它会告诉你,当前是在哪个分支(master)提交的, 本次提交的完整 SHA-1 校验和是什么(bef8ce0),以及在本次提交中,有多少文件修订过,多少行添改和删 改过。记住,提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入 版本管理。每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。

跳过使用暂存区域

尽管使用暂存区域的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。Git 提供了一个跳过使用 暂存区域的方式,只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂 存起来一并提交,从而跳过 git add 步骤:

~/Desktop/gitDemo(master) » git status                                                              liuxingxing@liuxingxingdeMacBook-Pro
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.md

no changes added to commit (use "git add" and/or "git commit -a")
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git commit -a -m '修改README文件'                                      liuxingxing@liuxingxingdeMacBook-Pro
[master f7c0e19] 修改README文件
 1 file changed, 1 insertion(+), 1 deletion(-)

移除文件

现在,gitDemo里面有2个文件,分别是README.md和Text.md两个文件,分支已经提交.

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提 交。可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪 文件清单中了。如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部 分(也就是未暂存清单)看到.

现在我们直接在目录中删除Text.md文件,然后查看项目状态:

~/Desktop/gitDemo(master*) » ~/Desktop/gitDemo(master) » git status                                                              liuxingxing@liuxingxingdeMacBook-Pro
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:    Text.md

no changes added to commit (use "git add" and/or "git commit -a")

现在,我们运行 git rm 记录此次移除文件的操作,看看和刚才有什么不同:

~/Desktop/gitDemo(master*) » git rm Text.md                                                         liuxingxing@liuxingxingdeMacBook-Pro
rm 'Text.md'
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    Text.md

--------------------------------------------

可以看到,原来的Text.md文件被标记为”Changes not staged for commit:”,但是执行过git rm Text.md 命令之后,Text.md文件已经被标记为”Changes to be committed”,也就是可以直接运行commit命令提交了.执行commit之后,该文件就不再纳入版本管理了。如果删除之前修改过并且已经放到暂存区域的话,则必须 要用强制删除选项 -f(译注:即 force 的首字母),以防误删除文件后丢失修改的内容。

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作 目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆 .a 编译文件,不小心纳入仓库 后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 –cached 选项即可:

git rm --cached README

移动文件

Git 并不跟踪文件移动操作。如果在 Git 中重命名了某个文件,仓库中存储的元数 据并不会体现出这是一次改名操作。

现在,gitDemo里面有2个文件,分别是README.md和Text.md两个文件,分支已经提交.假如现在你想将README.md改名为READ,可以这样做:

~/Desktop/gitDemo(master) » git mv README.md README                                                 liuxingxing@liuxingxingdeMacBook-Pro
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

------------------------------------------

此时查看状态信息,也会明白无误地看到关于重命名操作的说明,此时,该README文件已经处于可以被commit的状态了.

看到git mv命令,你可能会感到困惑,我明明只是希望给文件改个名字,怎么会执行git mv命令呢?其实,运行 git mv 就相当于运行了下面三条命令:

~/Desktop/gitDemo(master) » mv README.md README 
~/Desktop/gitDemo(master) » git rm README.txt
~/Desktop/gitDemo(master) » git add README

如此分开操作,Git 也会意识到这是一次改名,所以不管何种方式都一样。当然,直接用 git mv 轻便得多.

查看提交历史

在提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,可以使用 git log 命令。

git  log
//用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新
git log –p -2

//--stat,仅显示简要的增改行数统计
git log --stat

//--pretty 选项,可以指定使用完全不同于默认格式的方式展示提交历史。
//比如用 oneline 将每 个提交放在一行显示,这在提交数很大时非常有用。
//另外还有 short,full 和 fuller 可以用,展示的信息或多
//或少有些不同,请自己动手实践一下看看效果如何。
git log --pretty=oneline

it log --pretty=format:"%h - %an, %ar : %s"
//--since 和 --until 列出所有最近两周内的提交
git log --since=2.weeks

撤消操作

任何时候,你都有可能需要撤消刚才所做的某些操作。注意,有些操作并不总是可以撤消的,所以请务必谨慎小心,一旦失误,就有可能丢失部分工作成果。

修改最后一次提交

有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以 使用 –amend 选项重新提交.

比如,我们刚刚修改了README文件,为里面增加了为里面的文字增加了”111111111111”内容,然后提交了记录.但是我们突然发现,我们还需要修改一下Text.md文件,将Text.md文件里面增加内容”222222222”然后一起提交,可是我们已经提交了记录:

~/Desktop/gitDemo(master) » git status                                                              liuxingxing@liuxingxingdeMacBook-Pro
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")
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git commit -a -m '为README问件增加内容为111111111111'                  liuxingxing@liuxingxingdeMacBook-Pro
[master bac98db] 为README问件增加内容为111111111111
 1 file changed, 1 insertion(+)
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master) » git status                                                              liuxingxing@liuxingxingdeMacBook-Pro
On branch master
nothing to commit, working tree clean

此时使用 –amend就可以解决这个问题.注意,如果此时文件没有改动,或者改动了并没有 add文件,是文件并没有处于可以commit状态,那么运行git commit --amend命令只是相当于有 机会重新编辑提交说明,而所提交的文件快照和之前的一样。

~/Desktop/gitDemo(master) » git status                                                              liuxingxing@liuxingxingdeMacBook-Pro
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:   Text.md

no changes added to commit (use "git add" and/or "git commit -a")


git commit --amend

git commit –amend运行后,vim会让你重新编写提交记录,当你重新编辑提交记录后, :wq之后则意味着操作已经完成.

取消已经暂存的文件

我们修改README文件,为里面增加了为里面的文字增加了”333333333”内容,修改一下Text.md文件,将Text.md文件里面增加内容”4444444444”然后一起提交,我们打算分开提交2个文件的记录,但是却不小心使用了git add .命令全部添加到了暂存区,现在我们使用命令git reset HEAD Text.md取消对Text.md的暂存:

~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README
    modified:   Text.md

-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git reset HEAD Text.md                                                 liuxingxing@liuxingxingdeMacBook-Pro
Unstaged changes after reset:
M    Text.md
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

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:   Text.md

---------------------------------------------------------------------------------

我们通过git status 命令查看文件状态的时候就提示了该如何撤消,所以不需要死记硬背.

取消对文件的修改

如果觉得刚才对 Text.md 的修改完全没有必要,该如何取消修改,回到之前的状态(也就是修改之 前的版本)呢?git status 同样提示了具体的撤消方法,接着上面的例子,现在未暂存区域看起来像这样:

~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

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:   Text.md

------------------------------------------

我们按照提示运行git checkout -- Text.md命令:

~/Desktop/gitDemo(master*) » git checkout -- Text.md                                                liuxingxing@liuxingxingdeMacBook-Pro
-----------------------------------------------------------------------------------------------------------------------------------------
~/Desktop/gitDemo(master*) » git status                                                             liuxingxing@liuxingxingdeMacBook-Pro
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

----------------------------------------------

可以看到,该文件已经恢复到修改前的版本。你可能已经意识到了,这条命令有些危险,所有对文件的修改 都没有了,因为我们刚刚把之前版本的文件复制过来重写了此文件。所以在用这条命令前,请务必确定真的不再需要保留刚才的修改。如果只是想回退版本,同时保留刚才的修改以便将来继续工作,可以用 stashing 和分支来处理,应该会更好些。记住,任何已经提交到 Git 的都可以被恢复。你可能失去的数据,仅限于没有提交过的, 对 Git 来说它们就像从未存在过一样。


   转载规则


《Git系统总结学习(一)》 刘星星 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Git系统总结学习(二) Git系统总结学习(二)
远程分支查看当前的远程库查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库
2017-06-03
下一篇 
在swift中使用Quartz 2D 在swift中使用Quartz 2D
在swift中使用Quartz 2D在iOS中,绘图技术主要有UIKit、Quartz 2D、Core Animation和OpenGL ES。其中,Core Animation提供动画实现技术,OpenGL ES是针对OpenGL
2017-05-21
  目录