git系列---基础使用

注: 该系列文章整理自《Pro Git》,非原创。git

在开始学习 Git 的时候,请努力分清你对其它版本管理系统的已有认识,如 Subversion 和 Perforce 等;这么作能帮助你使用工具时避免发生混淆。 Git 在保存和对待各类信息的时候与其它版本控制系统有很大差别,尽管操做起来的命令形式很是相近,理解这些差别将有助于防止你使用中的困惑github

git系列:

git系列--基础使用

git系列--分支

1、git思想和基本工做原理

1.1 直接记录快照,而非差别比较

Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差异在于 Git 对待数据的方法。其它大部分系统以文件变动列表的方式存储信息, 这类系统(CVS、Subversion、Perforce、Bazaar 等等)将它们保存的信息看做是一组基本文件和每一个文件随时间逐步累积的差别。数据库

Git 更像是把数据看做是对小型文件系统的一组快照。每次你提交更新,或在Git中保存项目状态时,它主要对当时的所有文件制做一个快照并保存这个快照的索引。 为了高效,若是文件没有修改,Git再也不从新存储该文件,而是只保留一个连接指向以前存储的文件。 Git 对待数据更像是一个快照流。安全

这种对待数据的方式,使得git分支管理特别强大。bash

1.2 近乎全部操做都是本地执行

在 Git 中的绝大多数操做都只须要访问本地文件和资源,通常不须要来自网络上其它计算机的信息,等有网络时,再更新到服务器上。由于你在本地磁盘上就有项目的完整历史,因此大部分操做看起来瞬间完成。服务器

1.3 三种状态和三个工做区域

Git 有三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。已提交表示数据已经安全的保存在本地数据库中。已修改表示修改了文件,但还没保存到数据库中。已暂存表示对一个已修改文件的当前版本作了标记,使之包含在下次提交的快照中。网络

由此引入 Git 项目的三个工做区域的概念:Git仓库工做目录以及暂存区域工具

Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。post

工做目录是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。学习

暂存区域是一个文件,保存了下次将提交的文件列表信息,通常在 Git 仓库目录中。 有时候也被称做“索引”,不过通常说法仍是叫暂存区域。

基本的 Git 工做流程以下:

  1. 在工做目录中修改文件。
  2. 暂存文件,将文件的快照放入暂存区域。
  3. 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。

若是 Git 目录中保存着特定版本的文件,就属于已提交状态。若是做了修改并已放入暂存区域,就属于已暂存状态。若是自上次取出后,做了修改但尚未放到暂存区域,就是已修改状态。

1.4 用户信息

当安装完 Git 应该作的第一件事就是设置你的用户名称与邮件地址。 这样作很重要,由于每个Git的提交都会使用这些信息,而且它会写入到你的每一次提交中,不可更改:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
复制代码

若是想要检查你的配置,可使用 git config --list 命令来列出全部 Git 当时能找到的配置。

$ git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
复制代码

你能够经过输入 git config : 来检查 Git 的某一项配置

$ git config user.name
John Doe
复制代码

2、git基础使用

本章目标:配置并初始化一个仓库(repository)、开始或中止跟踪(track)文件、暂存(stage)或提交(commit)更改。 本章也将向你演示如何配置Git来忽略指定的文件和文件模式、如何迅速而简单地撤销错误操做、如何浏览你的项目的历史版本以及不一样提交(commits)间的差别、如何向你的远程仓库推送(push)以及如何从你的远程仓库拉取(pull)文件

2.1 获取Git仓库

有两种取得 Git 项目仓库的方法。

  1. 第一种是在现有项目或目录下导入全部文件到 Git 中;
  2. 第二种是从一个服务器克隆一个现有的 Git 仓库。

2.1.1 在现有目录中初始化仓库

若想对现有的项目进行管理,只须要进入该项目目录并输入:

$ git init

该命令将会建立初始仓库。会建立一个名为 .git(隐藏文件) 的子目录,这个子目录含有你初始化的Git仓库中全部的必须文件,这些文件是Git仓库的骨干。

可是,在这个时候,咱们仅仅是作了一个初始化的操做,你的项目里的文件尚未被跟踪维护。若是该文件夹已经存在文件,你能够开始跟踪这些文件并提交。

$ git add *.c  //添加后缀为.c的文件
$ git add LICENSE //添加LICENSE
$ git add . //添加全部文件
$ git commit -m 'initial project version' //提交
复制代码

如今,你已经获得了一个实际维护(或者说是跟踪)着若干个文件的 Git 仓库。

2.1.2 克隆现有仓库

若是你想得到一份已经存在了的Git仓库的拷贝,好比github上某个开源项目。这时就要用到git clone命令。Git克隆的是该Git仓库服务器上的几乎全部数据,而不是仅仅复制完成你的工做所须要文件。 当你执行 git clone命令的时候,默认配置下远程 Git 仓库中的每个文件的每个版本都将被拉取下来。事实上,若是你的服务器的磁盘坏掉了,你一般可使用任何一个克隆下来的用户端来重建服务器上的仓库。

克隆仓库的命令格式是 git clone [url]。 好比,要克隆 Git 的可连接库 ,能够用下面的命令:

$ git clone https://github.com/XWayne/TapeView.git
复制代码

这会在当前目录下建立一个名为 “TapeView” 的目录,并包含项目中的文件。 若是你想在克隆远程仓库的时候,自定义本地仓库的名字,你可使用以下命令:

$ git clonehttps://github.com/XWayne/TapeView.git myTape

复制代码

这将执行与上一个命令相同的操做,不过在本地建立的仓库名字变为 myTape。

2.2 记录每次更新到仓库

工做目录下的全部文件,对于git来讲,只有两种状态:已跟踪或未跟踪 ;已跟踪文件指那些被归入版本控制的文件,上次快照中有他们的记录,工做一段时间后,可能处于未修改,已修改或已放入暂存区;除已跟踪文件之外的全部其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。对于初次克隆某个仓库的时候,工做目录中的全部文件都属于已跟踪文件,并处于未修改状态。

编辑已跟踪文件后,Git将它们标记为已修改文件,咱们将这些修改文件放入暂存区后就处于已放入暂存区,提交后,就又恢复成未修改状态。

2.2.1 检查当前文件状态

要查看哪些文件处于什么状态,能够用git status命令。如在克隆仓库后当即使用此命令,会看到相似的输出:

$ git status
On branch master
nothing to commit, working directory clean
复制代码

这说明你如今的工做目录至关干净。换句话说,全部已跟踪文件在上次提交后都未被更改过,也没有出现任何处于未跟踪状态的新文件

如今,建立一个新的README文件,若是以前不存在,再次运行git status命令,会看到新的未跟踪文件:

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

    README

nothing added to commit but untracked files present (use "git add" to track)
复制代码

在状态报告中能够看到新建的 README 文件出如今 Untracked files 下面。

2.2.2 跟踪新文件

使用命令 git add 开始跟踪一个文件。 因此,要跟踪 README文件,运行:

$ git add README
复制代码

此时再运行git status命令,会看到README文件已被跟踪,并处于暂存状态:

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

    new file:   README
复制代码

在 Changes to be committed 这行下面的,就说明是已暂存状态。

2.2.3 暂存已修改文件

如今修改一个已被跟踪的,名为 CONTRIBUTING.md的文件而后运行 git status 命令,会看到下面内容:

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

    new file:   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:   CONTRIBUTING.md
复制代码

文件 CONTRIBUTING.md 出如今 Changes not staged for commit这行下面,说明已跟踪文件的内容发生了变化,但尚未放到暂存区。

要暂存此次更新,须要运行git add命令。这是个多功能命令:

  1. 能够用它开始跟踪新文件,或者把已跟踪的文件放到暂存区
  2. 还能用于合并时把有冲突的文件标记为已解决状态等。

将这个命令理解为 “添加内容到下一次提交中” 而不是“将一个文件添加到项目中”要更加合适。

咱们运行 git add 将"CONTRIBUTING.md"放到暂存区,而后再看看 git status 的输出:

$ git add CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md
复制代码

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

2.2.4 提交更新

提交命令:

$ git commit -m "你要写的本次提交的备注信息"
复制代码

请记住,提交时记录的是放在暂存区域的快照。任何还未暂存的仍然保持已修改状态,能够在下次提交时归入版本管理。每一次运行提交操做,都是对你项目做一次快照,之后能够回到这个状态,或者进行比较。

2.2.5 跳过使用暂存区域

Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给git commit 加上 -a 选项,Git就会自动把全部已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:

2.2.6 忽略文件

通常咱们总会有些文件无需归入Git的管理,也不但愿它们总出如今未跟踪文件列表。 一般都是些自动生成的文件,好比日志文件,或者编译过程当中建立的临时文件等。 在这种状况下,咱们能够建立一个名为 .gitignore 的文件,列出要忽略的文件模式。

参考:

  1. 忽略特殊文件
  2. 官方准备的各类配置文件

2.2.7 移除文件

要从 Git 中移除某个文件,即要从已跟踪文件清单中移除,并连带从工做目录中删除指定的文件,可使用命令git rm <file>

$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    PROJECTS.md
复制代码

提交以后即完成这次操做。

若只想从Git仓库中删除,但仍但愿保留在工做目录即磁盘中(当你忘记添加 .gitignore 文件,不当心把一个很大的日志文件或一堆.a这样的编译生成文件添加到暂存区时,这一作法尤为有用),使用 --cached 选项:

$ git rm --cached README.txt
rm 'README.txt'

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

        deleted:    README.txt

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

        README.txt

复制代码

2.2.8 查看提交历史

查看提交历史,是git log命令

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit
复制代码

默认不用任何参数的话,git log会按提交时间列出全部的更新,最近的更新排在最上面。正如你所看到的,这个命令会列出每一个提交的SHA-1校验和、做者的名字和电子邮件地址、提交时间以及提交说明。

更多git log 使用,参考:查看提交历史:git log

2.3 撤消操做

在任何一个阶段,你都有可能想要撤消某些操做。

注意:有些撤消操做是不可逆的。这是在使用 Git 的过程当中,会由于操做失误而致使以前的工做丢失的少有的几个地方之一。

2.3.1 从新提交

有时候咱们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。此时,能够运行带有 --amend 选项的提交命令尝试从新提交:

$ git commit --amend -m '新的提交信息'
复制代码

这个命令会将暂存区中的文件提交。若是自上次提交以来你还未作任何修改(例如,在上次提交后立刻执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。将代替上一次提交的结果。

2.3.2 取消暂存的文件

命令:git reset HEAD <file>...来取消暂存

你已经修改了两个文件而且想要将它们做为两次独立的修改提交,可是却意外地输入了 git add * 暂存了它们两个。如何只取消暂存两个中的一个呢? git status 命令提示了你:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md
复制代码

在 “Changes to be committed” 文字正下方,提示使用 git reset HEAD <file>...来取消暂存。 因此,咱们能够这样来取消暂存 CONTRIBUTING.md 文件:

$ git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M	CONTRIBUTING.md
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> 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:   CONTRIBUTING.md
复制代码

2.3.3 撤销对文件的修改

使用git checkout -- <file>命令来撤销文件的修改

若不想保留对文件的修改,即想恢复到上一次提交的样子,能够经过该命令取消(git status亦有提示)

$ git checkout -- CONTRIBUTING.md
复制代码

注意: 在Git中任何已提交的东西几乎老是能够恢复的。甚至那些被删除的分支中的提交或使用--amend选项覆盖的提交也能够恢复。然而,任何你未提交的东西丢失后极可能再也找不到

2.4 远程仓库的使用

为了能在任意Git项目上协做,你须要知道如何管理本身的远程仓库。远程仓库是指托管在因特网或其余网络中的你的项目的版本库。你能够有好几个远程仓库,一般有些仓库对你只读,有些则能够读写。与他人协做涉及管理远程仓库以及根据须要推送或拉取数据。管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不一样的远程分支并定义它们是否被跟踪等等。

2.4.1 查看远程仓库

若是想查看已经配置好的远程仓库服务器,能够运行git remote命令,会罗列出你配好的每个远程服务器的简写。(若是你已经克隆了本身的远程仓库,那么至少应该能看到origin,这是Git给你克隆的仓库服务器的默认名字)

$ git remote
origin
复制代码

你也能够指定选项 -v,会显示须要读写远程仓库使用的Git保存的简写与其对应的 URL。

$ git remote -v
origin  https://github.com/XWayne/TapeView.git (fetch)
origin  https://github.com/XWayne/TapeView.git (push)
复制代码

2.4.2 添加远程仓库

运行 git remote add <shortname> <url>添加一个新的远程Git仓库,同时指定一个你能够轻松引用的简写:

$ git remote add pb  https://github.com/XWayne/TapeView.git
$ git remote -v
origin  https://github.com/XWayne/TapeView.git (fetch)
origin  https://github.com/XWayne/TapeView.git (push)
pb      https://github.com/XWayne/TapeView.git (fetch)
pb      https://github.com/XWayne/TapeView.git (push)

复制代码

如今你能够在命令行中使用字符串 pb 来代替整个 URL。

2.4.3 从远程仓库中抓取与拉取

从远程仓库中得到数据,能够执行: $ git fetch [remote-name]

这个命令会访问远程仓库,从中拉取全部你尚未的数据。 执行完成后,你将会拥有那个远程仓库中全部分支的引用,能够随时合并或查看。

注意: git fetch命令会将数据拉取到你的本地仓库——它并不会自动合并或修改你当前的工做。当准备好时你必须手动将其合并入你的工做。

若是你有一个分支设置为跟踪一个远程分支,可使用git pull命令来自动的抓取而后合并远程分支到当前分支。

TODO:更多细节,后期分支再讲

2.4.4 推送到远程仓库

当你想分享你的项目时,必须将其推送到上游。 这个命令很简单:git push [remote-name] [branch-name]。 当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时一般会自动帮你设置好那两个名字),那么运行这个命令就能够将你所作的备份到服务器:

TODO:更多细节,后期分支再讲

2.4.5 查看某个远程仓库

若是想要查看某一个远程仓库的更多信息,可使用 git remote show [remote-name]命令

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/schacon/ticgit
  Push  URL: https://github.com/schacon/ticgit
  HEAD branch: master
  Remote branches:
    master                               tracked
    dev-branch                           tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)
复制代码

它一样会列出远程仓库的 URL 与跟踪分支的信息。 这些信息很是有用,它告诉你正处于 master 分支,而且若是运行 git pull,就会抓取全部的远程引用,而后将远程 master 分支合并到本地 master 分支。 它也会列出拉取到的全部远程引用。

2.4.6 远程仓库的移除与重命名

若是想要重命名引用的名字能够运行git remote rename 去修改一个远程仓库的简写名。 例如,想要将 pb 重命名为 paul,能够用 git remote rename 这样作:

$ git remote rename pb paul
$ git remote
origin
paul
复制代码

值得注意的是这一样也会修改你的远程分支名字。 那些过去引用 pb/master 的如今会引用 paul/master。

若是由于一些缘由想要移除一个远程仓库——你已经从服务器上搬走了或再也不想使用某一个特定的镜像了,又或者某一个贡献者再也不贡献了——可使用 git remote rm

$ git remote rm paul
$ git remote
origin
复制代码

注: 更多远程仓库的使用,参考:远程仓库的使用

2.5 打标签

Git 能够给历史中的某一个提交打上标签,以示重要。比较有表明性的是人们会使用这个功能来标记发布结点(v1.0 等等)。

2.5.1 列出标签

在 Git 中列出已有的标签是很是简单直观的。 只须要输入 git tag以字母顺序列出标签):

$ git tag
v0.1
v1.3
复制代码

你也可使用特定的模式查找标签。 例如,Git 自身的源代码仓库包含标签的数量超过 500 个。 若是只对 1.8.5 系列感兴趣,能够运行:

$ git tag -l 'v1.8.5*'
v1.8.5
v1.8.5-rc0
v1.8.5-rc1
v1.8.5-rc2
v1.8.5-rc3
v1.8.5.1
v1.8.5.2
v1.8.5.3
v1.8.5.4
v1.8.5.5
复制代码

2.5.2 建立标签

Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。

一个轻量标签很像一个不会改变的分支——它只是一个特定提交的引用。

然而,附注标签是存储在 Git 数据库中的一个完整对象。 它们是能够被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;而且可使用 GNU Privacy Guard (GPG)签名与验证。 一般建议建立附注标签,这样你能够拥有以上全部信息;可是若是你只是想用一个临时的标签,或者由于某些缘由不想要保存那些信息,轻量标签也是可用的。

(1)附注标签

在 Git 中建立一个附注标签是很简单的。 最简单的方式是当你在运行 tag 命令时指定 -a 选项:

$ git tag -a v1.4 -m "my version 1.4"
$ git tag
v0.1
v1.3
v1.4
复制代码

经过使用git show命令能够看到标签信息与对应的提交信息:

$ git show v1.4
tag v1.4
Tagger: Ben Straub <ben@straub.cc>
Date:   Sat May 3 20:19:12 2014 -0700

my version 1.4

commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number
复制代码
(2)轻量标签

轻量标签本质上是将提交校验和存储到一个文件中——没有保存任何其余信息。只须要提供标签名字:

$ git tag v1.99
$ git tag
v0.1
v1.3
v1.4
v1.5
v1.99
复制代码

这时,若是在标签上运行 git show,你不会看到额外的标签信息。 命令只会显示出提交信息:

$ git show v1.99
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number
复制代码

2.5.3 后期打标签

你也能够对过去的提交打标签。 假设提交历史是这样的:

$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
复制代码

如今,假设在 v1.2 时你忘记给项目打标签,也就是在 “updated rakefile” 提交。 你能够在以后补上标签。 要在那个提交上打标签,你须要在命令的末尾指定提交的校验和(或部分校验和):

$ git tag -a v1.2 9fceb02 -m "version 1.2"
复制代码

2.5.4 共享标签

默认状况下,git push命令并不会传送标签到远程仓库服务器上。 在建立完标签后你必须显式地推送标签到共享服务器上。 这个过程就像共享远程分支同样——你能够运行git push origin [tagname]

$ git push origin v1.0
复制代码

可在github项目的“release”中看到:

若是想要一次性推送不少标签,也可使用带有 --tags选项的 git push 命令。 这将会把全部不在远程仓库服务器上的标签所有传送到那里。

$ git push origin --tags
复制代码

如今,当其余人从仓库中克隆或拉取,他们也能获得你的那些标签。

2.5.5 删除标签

要删除掉你本地仓库上的标签,可使用命令 git tag -d <tagname>。例如,可使用下面的命令删除掉一个轻量级标签:

$ git tag -d v1.0
Deleted tag 'v1.0' (was 4e28e8f)
复制代码

应该注意的是上述命令并不会从任何远程仓库中移除这个标签,你必须使用 git push <remote> :refs/tags/<tagname>来更新你的远程仓库:

$ git push origin :refs/tags/v1.0
To https://github.com/XWayne/TapeView.git
 - [deleted]         v1.0

复制代码

2.6 Git别名

Git 并不会在你输入部分命令时自动推断出你想要的命令。 若是不想每次都输入完整的 Git 命令,能够经过 git config 文件来轻松地为每个命令设置一个别名。

$ git config --global alias.ci commit
复制代码

这意味着,当要输入 git commit 时,只须要输入 git ci

注: 更多别名的使用,参考:Git别名

备注

该系列文章笔记整理自《Pro Git》,非原创。

相关文章
相关标签/搜索