GIT初步

git现在是最流行的版本控制软件,大多数linux发行版已经默认安装,github等托管网站也越来越流行。每个程序员都需要学习git。

git最权威的教程是git pro。这里简单记下笔记,目的只是入门,介绍一些最简单和常用的操作命令。

1. git的基本工作模式

在git之前,最流行的版本控制软件是svn。svn非常简单易用,基本命令就三条:checkoutupdatecommit。svn只有两个区域,一个是服务器版本库,一个是本地工作区。checkout用来在最开始下载服务器的代码库,update用来获取服务器端的更新(来源于协助者),commit用来提交自己本地工作区的更新。

git则要复杂一些,这个复杂性大大增强了git的功能,这个暂且不谈。简而言之,对git用户而言存在四个区域,服务器版本库、本地版本库、暂存区和本地工作区。这比svn要多两个。这也让git的灵活性大大增加。最大的好处是,svn每次提交都必须联网,但git可以提交到本地版本库,等待联网时再同步到服务器版本库。

2. 获取代码库

使用git的第一步是下载服务器版本库到本地,类似于svn的checkout。要下载,需要先获得服务器的地址,现在很多项目都采取网络托管,流行的有githubgitcafeoschina。如果想自己成立一个新项目,可以去这几个地方,其中oschina可以免费建私有项目,githubgitcafe建私有项目是收费的,但公开项目仍然免费。

假设我们有一个服务器版本库的地址http://xxx.com/yyy/zzz,下面命令便能建立一个本地版本库开始工作:

git clone http://xxx.com/yyy/zzz

它会在当前目录下新建zzz目录,目录下是工作文件。除了正常代码文件外,还有一个.git的文件夹,里面便保存了版本信息。我们一般都不用理会它。

我们也可以指定下载的文件夹

git clone http://xxx.com/yyy/zzz abc

此处abc可以是相对位置,也可以是绝对位置。如果abc不存在,git将新建该文件夹。abc的末尾可以带斜杠也可以不带。

如果想直接下载到当前文件夹,可以用.表示:

git clone http://xxx.com/yyy/zzz .

clone的过程中,目标文件夹一定要是空的。如果已经有一些本地文件需要放入版本库,可以先clone到另外一个文件夹,再复制本地文件到版本库,再把版本库挪到当前文件夹。

比如当前目录已经有一些文件,我们可以这么做:

git clone http://xxx.com/yyy/zzz ../tmp # 假设../tmp文件夹不存在或是空的
cp ./. ../tmp/ -ra
cp ../tmp/. ./ -ra
rm ../tmp -rf

它的一个基本思路是git的工作目录其实是可以移来移去。

3. 提交自己的代码

现在程序员需在下载到本地的代码上开始自己的编程工作,然后修改了一些代码,新增了几个文件等等。接下来的操作和svn就有很大区别了。

在本地,git有三个区域,一个是工作区域(就是你不断修改代码的地方),一个是暂存区域,一个是本地版本库区域。对于一个已经纳入版本库的文件,根据处于位置的不同,就有三种状态,一种是未暂存,一种是已暂存未提交,第三种是已提交。

如果新增一个文件,其第一步是将其纳入版本库。把文件放入暂存区,就是纳入到版本库。

当文件提交到本地版本库后,最终还需要同步到网络共享服务器上。所以一个文件其实有四个状态(svn则只有两个状态)。一个修改的文件,需要经过三步,才能被其它共享者看到。这三步分别是:addcommitpush

3.1. status查看状态

使用git status命令可以看到当前文档的状态。包括

  • 目前本地版本库还有几个提交未同步到网络版本库,即ahead of 'origin/master' by 1 comment即目前还有一个本地提交未同步到网络共享版本库。
  • 未提交的修改:Changes to be committed
  • 未暂存的修改:Changes not stagged for commit
  • 未纳入新版本的修改:Untracked files

git status显示的信息示例如下:

# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#   (use "git push" to publish your local commits)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:  xxx/abc
#
# 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:  yyy/edf 
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       zzz/ijk

有一些中间文件,比如C++编译产生的.o文件,不用纳入到版本控制中,但它总是会显示在此处的Untraced files列表。通过编辑.gitignore,可以在此列表自动排除掉指定文件:

# ./.gitignore
*.o

.gitignore文件也支持通配符,可以排除特定文件夹和特定文件类型。

.gitignore文件是递归调用的。当查看一个文件是否该忽略时,直接查找当前目录的.gitignore,若没有则往上查询,直到根目录为止。因此可以在不同文件夹下放置不同的.gitignore文件。

3.2. add添加文件到暂存区

无论是新建的文件,还是修改过的文件,都可以通过add命令将其添加到暂存区:

git add path/to/file

add已支持通配符:

git add path/to/*

注意上面这个会把所有path/to/目录下所有文件都加入暂存区。如果该目录下有.gitignore要求忽略的文件,该提交会出错。此时有两种方法,一种方法是增加-f参数:

git add path/to/* -f

另一种方法是不要用通配符,只用目录,此时.gitignore要求忽略的文件会被自动忽略:

git add path/to/ 

参数A可以把删除行为也提交到暂存区:

rm test.c
git add -A . # test.c的删除也被更新到暂存区

add会自动忽略.gitignore里指定忽略的文件。要想添加已要求指定忽略的文件,需添加-f参数:

git add test.o # not works because *.o is ignored in .gitignore
git add -f test.o # this works

另外一个需注意的地方是,git只针对文件,不针对目录。所以无法添加空目录到版本库。如果实在要的话怎么办呢?可以在该目录下添加一个空的.gitignore文件,再把这个文件添加到版本库。这样这个空目录就能添加到版本库了。当需删除该目录时,在版本库里删除该.gitignore文件即可。

如果有多个空目录,可以用下面bash命令同时添加.gitignore文件:

$ find . \( -type d -empty \) -and \( -not -regex ./\.git.* \) -exec touch {}/.gitignore \;

3.3. commit提交到本地存档

commit将暂存档里的文件保存到本地版本库。在commit前,可以运行多次add命令。参数-m用来指定提交的参考信息。

git commit -m 'bla bla...'

如果提交时无需做特别的选择,addcommit可合二为一,在commit时指定参数-a,可以自动将所有的修改添加到暂存档,同时提交:

git commit -a -m 'bla bla...'

3.3.1. commit --amend修改最后一次提交

有时候提交之后发现有几个文件没有贴上,commit --amend给了一次后悔的机会,它将把当前暂存区的文件和上次提交合并再次提交:

git commit -m 'init commit'
git add forgotten_files
git commit --amend

提交之后没有改动直接运行commit --amend则有机会重新编辑提交说明。

3.4. push同步到网络版本库

程序员可以无限制地通过commit向本地版本库提交更新,但此时其它人还看不到这些更新。这时候可以通过push将本地版本库更新到网络共享版本库。

git push

3.5. pull更新本地版本库

当其它程序员通过push更新了网络共享版本,这时候我们应该把他们的更新下载下来,并在其基础上继续接下来的工作。pull命令便是完成此事:

git pull

根据情况不同,会出现几种不同的情况。

  • 如果本地还没有任何提交,并且网络上的更新的文件在本地没有被更新,这时候网络版本直接下载到本地版本。
  • 如果本地还有未提交的修改,并且同一文件被其它人修改并更新到了网络共享版本库,这时候会出错。这时候需先把当前工作区或暂存区的修改提交,然后再次pull
  • 如果本地已经有提交,同时和网络上的更新修改了同样的文件。如果这两方面的修改没有冲突(比如修改不同文件,或者修改同一文件的不同位置),git将自动进行合并,并且生成一个新的提交(到本地版本库)。
  • 如果这两方面的修改有冲突(一般只修改了同一文件的相同位置),git将合并文件。

合并的文件一般长下面这样:

<<<<<<< HEAD
ver 1
=======
ver 2
>>>>>>> HASHIDFORLASTCOMMIT

此时用户需自行删除一些行,然后重新addcommit

4. 回退到历史版本

版本控制的一个最大的功能(尤其是对于单个开发者的项目)便是保存历史修改记录,以便随时可以撤销修改回退到历史版本。由于git的文件有多个状态,所以回退也有几种情况:

4.1. 回退到上次暂存状态

这个是指在把文件放到暂存区之后,又修改了文件,这时候想把文件回退到暂存区的状态,此时可以用checkout的命令:

git checkout -- path/to/file.post

4.2. 回退到上次提交的状态

reset可以将文件恢复到上次提交的状态:

git reset HEAD 

4.3. 取消本地所有修改和提交

git reset可以取消本地所有修改和提交:

git reset --hard origin/master
Copyright © zhiqiang.org 2016 all right reserved,powered by Gitbook该文件修订时间: 2016-08-03 01:06:06

results matching ""

    No results matching ""