前言

Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
分布式相比于集中式的最大区别在于开发者可以提交到本地,每个开发者机器上都是一个完整的数据库,所以公共服务器压力和数据量都不会太大。并且它速度快、灵活,任意两个开发者之间可以很容易的解决冲突。并且可以快速新建及切换分支,重置任意文件或文件夹到某个历史版本,把以对于突发需求能更做到更快更好的响应,对敏捷开发尤其方便。

本文将对git的使用进行流程化的介绍,如果你只是想查看相关命令,可以移步Git 参考手册,本文部分内容摘自该手册。

Git的配置

配置用户名:git config --global user.name "YOUR NAME"
配置邮箱:git config --global user.email "YOUR EMAIL ADDRESS"
当你在本机配置好用户名和邮箱后,以后你在本机的所有git提交,都会以你设置的用户名和邮箱进行签名。

获取与创建项目

拥有一个 Git 仓库的途径有两种:

  1. 在已有的目录中,初始化一个新的.比如一个新的项目,或者一个已存在的项目,但该项目尚未有版本控制。
  2. 仓库克隆.如果你想要复制一份别人的项目, 或者与别人合作某个项目,也可以从一个公开的 Git 仓库克隆。
git clone 复制一个 Git 仓库

如果你需要与他人合作一个项目,或者想要复制一个项目,看看代码,你就可以克隆那个项目。 执行:git clone [GIT_REPOSITORY_URL]进行克隆,如https://github.com/defei/codelogger-utils.git

如果该项目需要进行身份授权验证,你可能需要输入用户名及密码。推荐的方式是使用ssh key进行身份授权验证。

上述操作将复制该项目的全部记录,让你本地拥有这些。并且该操作将拷贝该项目的主分支, 使你能够查看代码,或编辑、修改。进到该目录中,你会看到 .git 子目录。 所有的项目数据都存在那里。

git init 将一个目录初始化为 Git 仓库

如果你还没有git项目,可以进行git init来新建及初始化项目:

Git的版本管理

Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比,在此我们将这个快照称作版本。

Summary:使用 git add 添加需要追踪的新文件和待提交的更改, 然后使用 git statusgit diff 查看有何改动, 最后用 git commit 将你的快照记录。这就是你要用的基本流程,绝大部分时候都是这样的。

#####git add 添加文件到缓存
在 Git 中,在提交你修改的文件之前,你需要把它们添加到缓存,只有在缓存中的文件才会在commit的时候添加到版本管理中去。

命令说明:git add [target]
target可以是单个文件,或该git仓库中的任意目录中的所有文件。

假设当前git仓库中有如下文件结构:

.
|-- hello.md
`-- resources
    |-- hello.app
    `-- hello.jpg
1 directory, 3 files

则有如下几种操作方法:

  • git add .:表示将当前目录下的所有文件及文件夹加入到git缓存中去。
  • git add hello.md:表示只将hello.md这个文件添加到git缓存中去。
  • git add resources:表示只将resources文件夹添加到git缓存中去。
  • git add resources/hello.app:表示只将resources目录下的hello.app添加到git缓存中去。

如果要一次添加多个文件或文件夹,可以用空格分开,如:git add hello.md resources,这个命令会把hello.md和resources都添加到git缓存中去。

git status 查看你的文件在工作目录与缓存的状态

执行 git status 命令可查看从你上次提交之后当前git仓库中文件的状态,查看文件的增删改情况,以决定是否需要进行版本提交。

git status会列出完整的变更信息及git操作提示。如果你已经非常熟练的知道git操作,可以用git status -s来简化输出信息。

git diff 显示已缓存与已修改但未缓存的改动的区别

git diff命命用于检查版本之间的数据变动,常用命令如下:

  • git diff [FILE | DIRECTORY]:显示当前工程中,指定的file或directory与已经缓存版本的区别,如果已提交的文件没有使用git add添加到缓存中,则该文件会与前一个版本做比较。
  • git diff --cached [FILE | DIRECTORY]:显示已添加到缓存中的文件与前一个版本的区别。
  • git diff [HEAD | COMMIT-HASH]:显示当前git仓库中所有文件与指定版本之间的所有更改,HEAD表示上一次提交的版本,不区分大小写。
  • git diff --stat:如果我们不想要看整个 diff 输出,但是又想比 git status 详细点, 就可以用 –stat 选项。该选项使它显示摘要而非全文。
  • git diff [COMMIT-HASH] [COMMIT-HASH]显示两个版本之前的所有差异。
git commit 提交一个版本

当我们已经用git add添加了要提交的文件,并且通过git diff确认你的提交无误后,就可以用git commit来进行版本提交了。

如果只使用git commit来提交,会打开本机的默认文本编辑器,让你输入本次提交的说明信息,如果你不想使用文本编辑器来输入,可以使用git commit -m 'commit informations'来快速设置本次提交的说明信息。
如果你觉得提交流程太过繁锁,可以使用git commit -a来提交已受版本管理的所有提交,包括对文件的删除及重命名,不过该操作不适用于新加文件。对于新建的文件,因为没有受版本管理,所以还是需要用到git add来添加到缓存中来提交。

git reset 重置版本信息

如果你想放弃本次更改或快速清除提交到缓存中的信息,就可以用到git reset命令了,常用命令如下:

  • git reset [HEAD | COMMIT-HASH]:清除当前缓存中的所有信息,相当于你从上次提交(HEAD)或指定版本(COMMIT-HASH)后,没有执行过git addgit rm操作。
  • git reset [HEAD | COMMIT-HASH] --hard:强制恢复到指定版本,并清除所有更改。注意,该操作不可恢复,所以除非你非常确定不保留任何更改信息,不然尽量少用–hard参数。
git rm 将文件从版本控制中移除

git rm [FILE | DIRECTORY] 会将条目从版本控制中移除。这与 git reset HEAD 将条目取消缓存是有区别的。 “取消缓存”的意思就是将缓存区恢复为我们做出修改之前的样子。 在另一方面,git rm则将该文件彻底从版本控制中踢出。

如果你只想删除该文件的版本控制,但保留该文件,可用git rm --cached [FILE | DIRECTORY]进行移除版本控制操作。

git mv 移动被版本控制的文件

不像绝大多数其他版本控制系统,Git 并不记录记录文件重命名。它反而只记录版本提交,并对比版本提交以找到有啥文件可能被重命名了。 如果一个文件从更新中删除了,而在下次版本提交中新添加的另一个文件的内容与它很相似,Git 就知道这极有可能是个重命名。 因此,虽然有 git mv 命令,但它做得所有事情就是 git rm --cached, 重命名磁盘上的文件,然后再执行 git add 把新文件添加到缓存区。

分支与合并

分支Git的精华所在,你可以用git branch [branch name]在不同的分支之间来回切换,然你在一条主线上做开发,但有bug需要马上处理的时候,它就能发挥用处了。

大致流程就是:你可以执行 git branch (branch-name) 来创建分支, 使用 git checkout (branch-name) 命令切换到该分支,在该分支的上下文环境中, 提交版本等,之后可以很容易地来回切换。当你切换分支的时候,Git 会用该分支的最后提交的版本替换你的工作目录的内容, 所以多个分支不需要多个目录。使用 git merge 来合并分支。你可以多次合并到统一分支, 也可以选择在合并之后直接删除被并入的分支。

git branch 列出、创建与管理分支

git branch可以查看及管理当前git仓库中的分支,常用命令如下:

  • git branch [-a]:列出本地仓库的所有分支,如果加上-a则会列出本地及远程的所有分支情况。你所在的分支前会以’*’号进行标记。
  • git branch [branch-name]: 创建新分支。新创建的分支停留在你最后一次提交的版本,并拥有你当前分支的所有版本信息。在创建分支成功以后,你在当前分支做的所有更改,并不会影响已创建的分支。
  • git branch -d [branch-name]:删除本地分支。

使用git checkout -b [branch-name]可以快速创建并切换到分支。

git checkout 检出文件/切换分支
  • git checkout [branch-name]:切换分支到给定的分支。
  • git checkout [FILE | DIRECTORY]:重置指定的文件或文件夹到最后一次提交的版本。

如果你有一个文件和分支名相同的时候,checkout只能用于重置文件,并且只能使用命名git checkout -- [FILE | DIRECTORY]

git stash临时缓存所有更改

git stash可以将当前git仓库下新的更改放入git的临时工作目录下,以方便快速切换到其它工作上去。
git stash pop可以取出前一次stash的所有更改.

git stash是以栈(stack)模式工作的,也就是遵循后进先出的原则,你可以进行多次stash及stash pop。

git merge 合并分支

一旦某分支完成了新的功能开发并且测试充分,你可以使用 git merge [branch-name] 命令将任何分支合并到当前分支中去。

只要没有多个人员同时更改同一个文件中的同一块代码区域,一般就不会出现版本冲突,包括并不限于内容的理发,重命名,位置移动,删除等操作。

在自动合并完成后,git会自动提交一个版本信息,标明该合并信息。

如果合并中出现冲突,git会给出下的提示信息:

$ git merge test
Auto-merging test
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
$ cat README.md 
<<<<<<< HEAD
version 1.0.0
=======
version 1.0.1
>>>>>>> test

提示README.md有冲突,需要你手动解决冲突。”<<<<<<< HEAD” 到 “=======” 之间的代码是你当前分支的内容,”=======” 到 “>>>>>>> test” 之间的内容是合并的分支的内容,你可以根据你的情况删除不需要的内容(包括”<<<<<<< HEAD” , “=======” 和 “>>>>>>> test”),使用git add添加到缓存,并git commit提交这次合并。

到此,你已经将要全并的分支合并到当前分支了,如果被合并的分支已经没有用了,可以用`git branch -d [branch-name]’删除。

git log显示一个分支中提交的版本更改记录

git log可以查看当前分支中以提交时间倒序排列的所有版本信息,常用命令如下:

  • git log:显示完整的版本提交信息,包括版本hash值,提交者及邮件,提交日期,提交说明。
  • git log --oneline:提示版本提交的简要信息,包括版本hash的前7位及提交说明。一般情况下,版本hash的前7位已经足以定位一个版本,所以我们可以只用这7位值进行版本操作,比如git reset dd574cc
  • git log --graph:开启了拓扑图显示。

使用git log --oneline --graph可以更清楚明了地看到何时工作分叉、又何时归并。 这对查看发生了什么、应用了什么改变很有帮助,并且极大地帮助你管理你的分支。
在git log视图中,可以按’h’键打开帮助界面,获取更多信息。其实操作的vim几乎一样,如 ‘b’:上一页, ‘f’:下一页, ‘/RegExp’:按正则表达示查找.

git tag 给一个里程碑打上标签

如果你的项目已经达到一个里程碑阶段,并希望永远记住这个版本,你可以使用 git tag 给它打上标签。 通常,你会在切取一个发布版本或者交付一些东西的时候打个标签,如:

git tag -a "v1.0.0" [COMMIT-HASH]

  • “v1.0.0”:是当前标签的值
  • -a:“创建一个带注解的标签”,从而使你为标签添加注解。不用 -a 选项也可以执行的,但它不会记录这标签是什么时候打的,谁打的,也不会让你添加个标签的注解,我并不推荐这样操作。
  • [COMMIT-HASH]:指定提交版本的hash值,如果不全,默认为最后一次提交。

如果你想要查看tag信息,可以使用git log --decorate来进行查看。

分享与更新

Git 并不像 Subversion 那样有个中心服务器。你自己本身就是一个git服务器,并且你可以添加多个远程服务器,进行代码的提交及合并。

简要流程就是,使用 git fetch 更新你的项目,使用 git push 分享你的改动。 你可以用 git remote 管理你的远程仓库。

git remote 显示和管理远端仓库

不像中心化的版本控制系统(客户端与服务端很不一样),Git 仓库基本上都是一致的,并且并可以同步他们,这使得当前仓库可以拥有多个远端仓库。

常用命令列表:

  • git remote [-a]:列出所有远端仓库,加上-a则会显示出具体的仓库地址,否则只显示仓库别名。
  • git remote add [alias] [url]:如果你想要以任何方式与一个新仓库沟通,最简单的方式通常就是把它添加为一个远端仓库。比如,我们在在本地新建一个codelogger-utils的文件夹mkdir codelogger-utils && cd codelogger-utils,执行git init以初史化仓库,并执行git remote add origin https://github.com/defei/codelogger-utils.git以添加一个origin远程仓库,再执行’git pull origin master’就可以把远程仓库的master分支pull下来了。
  • git remote rm [alias]:删除远程仓库别名。注意,该操作只会删除本地远程仓库的信息,但远程仓库还是存在的,并不会被删除。
git fetch从远端仓库下载新分支与数据

git fetch [remote-alias] 会使你与另一仓库同步,提取你本地所没有的数据,为你在同步时的该远端的每一分支提供书签。 这些分支被叫做“远端分支”,你可以将它们合并到当前分支,与其他分支作比较差异,查看那些分支的历史日志,等等。

git pull从远端仓库提取数据并尝试合并到当前分支

git pull [remote-alias] [branch],该命令就是在 git fetch 之后紧接着 git merge 远端分支到你所在的任意分支。

git push 推送你的分支数据到远端仓库

git push [remote-alias] [branch],就会将你的 [branch] 分支推送到 [alias] 远端上的 [branch] 分支。

当你试图推送到某个以被更新的远端分支时,会出现下面这种情况:

$ git push origin master
To https://github.com/defei/codelogger-utils.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/defei/codelogger-utils.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

你可以执行git pull origin master以获取并合并无端的数据,当合并成功后,你就可以执行git push origin master把你本地数据提交到远程仓库了。

后记

到此,git的基本操作已经全部介绍完了,git与Subversion等仓库还是有很大的不同的,其去中心化与branch是其精华所在,能够快速的做到版本切换,离线提交等快,大大提高工作效率。

希望本文对你有所帮助。




如果您觉得这篇文章对您有所帮助, 点我, 可以请我喝杯咖啡。
< 支付宝 | 微信 >
Published with Hexo and Theme by Kael
Flag Counter
X