git日常使用心得

As with many great things in life, Git began with a bit of creative destruction and fiery controversy.

版本控制

版本控制系统(VCS)是一套方便开发团队管理项目的工具。它可以追踪代码的每一次改动,并保存到特殊的数据库中。开发者可以轻松的将项目回滚到历史上的某一个版本上去。

分布式(Distributed)版本控制 是什么概念呢。在DVCS中,没有严格意义上的中央server,每一台用户终端都可以充当中央仓库的角色。因为用户终端并不是checkout了项目的快照,而是镜像了整个仓库。用户终端的仓库也可以互相推送自己的更新。

GIT的玄学哲学

Snapshots, Not Differences

Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方法。 概念上来区分,其它大部分系统(CVS、Subversion、Perforce、Bazaar 等等)将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。Git 不按照以上方式对待或保存数据。 反之,Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流。这种形式也为git超强的分支管理打下了基础。

Nearly Every Operation Is Local

本地仓库包含了完整的项目历史,所以不需要经常通过网络读取数据。

If you’re used to a CVCS where most operations have that network latency overhead, this aspect of Git will make you think that the gods of speed have blessed Git with unworldly powers. Because you have the entire history of the project right there on your local disk, most operations seem almost instantaneous.(仿佛速度之神赋予了git超脱这个世界的能量=。=)

Git Has Integrity

Git中所有数据在存储前都计算校验和,然后以校验和来引用。它用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串,基于 Git 中文件的内容或目录结构计算出来。Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。

img

三个概念

工作区

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

暂存区

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

仓库

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

仓库分为本地仓库(local, git commit的目的地)和远程仓库(remote, git push的终点)

初始配置

安装好git之后,通常需要配置个人信息

# --global参数表示全局配置
git config --global user.name "Your Name"
git config --global user.email "[email protected]"

在linux上,配置文件会出现在3处:

  • /etc/gitconfig 所有用户的配置。通常需要加--system进行更改
  • ~/.gitconfig~/.config/git/config当前用户的配置,上面的指令改动的文件
  • project/.git/config 项目配置,不使用--global参数时只会对当前项目生效

注:下面的配置会覆盖上面的配置 windows上一般配置文件在c:/users/$USER/.gitconfig.

可通过--list参数查看当前全部配置,也可指定key查询特定配置

git config –list
git config <key>

查看帮助

平时使用肯定少不了查文档,git的文档十分的

git help <verb>
git <verb> --help
man git-<verb>

img

创建仓库

本地初始化仓库

# 初始化当前目录
git init

命令执行后,在当前目录下会生成.git隐藏文件夹,这便是git的本地仓库。

拉取远程仓库

git clone https://github.com/monkeyWzr/wlz

如果仓库中包含子模块,可用如下指令同时拉取全部子模块:

git clone --recursive https://github.com/monkeyWzr/wlz

可以指定项目文件夹名称,如:

git clone https://github.com/monkeyWzr/wlz wzr

更改远程仓库地址

git remote set-url origin https://github.com/monkeyWzr/wlz

移除文件

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 "Changes not staged for commit" 部分(也就是 未暂存清单)看到:

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/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:    PROJECTS.md

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

然后再运行 git rm 记录此次移除文件的操作:

$ 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

下一次提交时,该文件就不再纳入版本管理了。 如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f (force)。

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一堆无用的文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:

$ git rm --cached README

git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。 比方说:

$ git rm log/\*.log

注意到星号 * 之前的反斜杠 \, Git 有它自己的文件模式扩展匹配方式,与shell不同。 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。

标签

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

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

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

附注标签

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

$ git tag -a v1.4 -m 'my version 0.1'
$ git tag
v0.1

-m 选项指定了一条将会存储在标签中的信息。 如果没有为附注标签指定一条信息,Git 会运行编辑器要求你输入信息。

通过使用 git show 命令可以看到标签信息与对应的提交信息:

$ git show v0.1
tag v0.1
Tagger: Administrator <[email protected]>
Date:   Wed Nov 9 15:58:38 2016 +0800

my version 0.1

commit fd028a395bb93ec86fea05b2583776bb1d8dbf26
Merge: 283acd7 e63a609
Author: Wu <[email protected]>
Date:   Wed Nov 9 23:49:34 2016 +0800

    Merge pull request #2 from yunlugu/master

    add new poem

输出显示了打标签者的信息、打标签的日期时间、附注信息,然后显示具体的提交信息。

轻量标签

另一种给提交打标签的方式是使用轻量标签。 轻量标签本质上是将提交校验和存储到一个文件中 - 没有保存任何其他信息。 创建轻量标签不需要任何选项,只需要提供标签名字:

git tag v0.1-dev

为历史提交打标签

我们可以对历史的提交记录做标签。先查看下记录:

$ git log --pretty=oneline
fd028a395bb93ec86fea05b2583776bb1d8dbf26 Merge pull request #2 from yunlugu/master
e63a6092ae04547be92662a42bec51d93f1d4108 add a poem
2e84807aa4e53b85806edf70a7bfda71722eed46 Merge pull request #1 from monkeyWzr/master
283acd7cca89513291d67698d525dd83fa09983c remove another file
196a007de17fb3a0fc591b5522fd2b230f17e807 change readme
f3abc7ebc47e1c5e7bffb210a11113c38a0b887a Create README.md
4f0004e46656b86b14a82810dc2bc0762107f022 Merge pull request #1 from DKAngel/master
080f32c1af7dd0a68f45120d16b70725bfeccdb6 Update wlz.md
251a36f2bdd340e1d70031dae260c208f5098a54 add some text
d5c223a1e52a75f1488571933b48eb3d485b76e6 first post

然后可指定校验和打上标签。

$ git tag -a 080f32c

推送标签

默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。

$ git push origin v0.1

也可以使用--tags一次推送全部标签

$ git push origin --tags

检出标签

在 Git 中你并不能真的检出一个标签,因为它们并不能像分支一样来回移动。 如果你想要工作目录与仓库中特定的标签版本完全一样,可以使用 git checkout -b [branchname] [tagname] 在特定的标签上创建一个新分支:

$ git checkout -b dev v0.1-dev

忽略文件

忽略文件或文件夹只在本地需要使用

此种情况为,文件或文件夹只在本地需要,不应该出现在远程仓库时。 在将忽略文件或路径更新到.gitignore后,若对于已经trace的文件,需要让git不再跟踪,执行下列命令:

//目标为文件夹则需加入-r参数
git rm --cache /path/to/file

文件或文件夹的改动不需要提交

有些文件或文件夹的改动不需要提交,则在更新.gitignore的同时也要执行执行:

git update-index --assume-unchanged logs/*.log

此种情况下需要每位成员都在自己的本地仓库执行上述命令。

更新

拉取更新

git pull

拉取子模块更新

git submodule update --init --recursive

强制更新

有时候需要使用远程版本,覆盖本地版本,可在项目目录下使用:

git fetch --all
git reset --hard origin/master

分支

查看分支

git branch -r #查看远程分支
git branch -a #查看所有分支

切换分支

git checkout branch_name

推送分支

本地的分支并不会自动与远程仓库同步,你必须显式地推送想要分享的分支。

git push origin wlz

删除分支

git branch -d branch_name

删除远程分支

git push origin --delete branch_name
comments powered by Disqus