git使用教程(二) 基础

PHP技术交流群 170855791

获取GIT仓库

    这里有2种方法可以获取git仓库。将一个本地已经存在的项目或文件夹导入到Git中;或者clone一个远程服务器上已经存在的Git仓库
初始化一个已经存在的文件夹
    要想将一个本地项目添加到git版本库中,需要做的就是进入到这个文件夹中,输入下面的命令:

$git init

    这个命令会在该项目的文件夹中创建一个叫.git的子文件夹,即本地git仓库目录,这是Git仓库的基础文件,用来保存元数据和对象数据。
    当你开始想要使用版本控制器管理一个存在的项目时,你应当先跟踪这个项目里的文件,之后提交这些文件。可以使用一条或者多条git add命令来指定你想要放入暂存区中的文件,如: 

$git add *.c
$git add README
$git commit -m 'inital project version'

克隆一个已经存在的git数据仓库
克隆一个远程数据仓库,需要使用git clone命令,该命令会将远程仓库里的全部内容克隆下来(但不包括.git/config以及gitignore文件),包括不同版本的相同文件。克隆的完整命令为:$git clone [url],例如:

$git clone git://github.com/schacon/grit.git

使用上条命令后即可创建一个名为grit的目录,其中包含了一个已经初始化好的.git文件夹,以及所有的项目文件。如果你想把克隆的文件保存为另一个文件名,可以使用下面的命令:

$git clone git://github.com/schacon/grit.git mygrit

这条命令将会创建一个mygrit的文件夹,并将克隆下来的所有文件放到该文件夹下。
Tips:Git支持多种传输协议。上面的例子中使用的是git协议,你也可以使用http协议,SSH协议等等。

记录Git仓库的变更信息
假设现在你已经拥有一个完整的git数据仓库,当你每次需要修改一些项目文件并将这些修改快照提交到你的git数据仓库中时,git都会获取一个项目状态信息并将其记录下来。
    需要注意的是:在你的工作目录中每个文件都属于下面2种状态之一:被跟踪和未被跟踪。被跟踪文件保存在最后的快照中,未被跟踪的文件存在工作目录中,但是它们没有被加载到你的最后快照中,也没有被加载到暂存区中,不参与版本控制。通过git add和git commit命令可以将它置入跟踪库中。被跟踪的文件有3种状态:
unmodify:文件已经存在库中,未修改,即版本库中的文件快照内容与工作目录中的文件内容完全一致。这种类型的文件有两个去处,如果它被修改,而成为modified。如果使用”git rm”移出版本库,则成为untracked文件。
modified:文件已修改,仅仅是修改,并没有进行其它操作。这个文件也有两个去处,通过”git add”可进入暂存(staged)状态,使用”git checkout”则丢弃修改,返因到unmodify状态。这个checkout很好理解,就是取出库中文件,覆盖当前文件吧。
staged:暂存状态。执得”git commit”则将修改同步到库中,这时库中的文件与本地文件又一致了,于是文件是unmodify状态。执行”git reset HEAD filenam”取消暂存,文件状态变为modified。

查看文件状态
查看文件状态的主要工具就是git的status命令,该命令会将工作目录中的文件与暂存区中的文件进行对比后,将结果输出到屏幕上。

$git status

该命令会列出当前项目中被跟踪文件的变动信息和状态,同时也会列出未被跟踪的文件。在所列出的信息中第一条信息:On branch master说明你当前所使用的分支为:master。这是一个默认分支,有关分支的信息在这里就不做说明了。
该命令有一个常用参数--p,列出状态信息的简写形式。

$ git status -s
AM README
A hello.rb

跟踪新文件(添加到暂存区)
git中,在你使用提交命令commit之前,必须先要使用add命令,将该文件添加到暂存区中,如果是新创建的文件,也需要使用add命令将该文件初始化并添加到暂存区中。如在工作目录中新建立一个名为README的文件,查看文件状态:

$ git status

显示出如下信息:

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

把它添加到暂存区中。

$git add README

此时在查看git版本库的文件状态,就会看到如下信息:

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached ..." to unstage)
#
# new file: README
#

如果此时提交,历史快照中将会记录文件被add时的版本信息。此外,如果add的是一个目录名,那么该目录下的所有文件都会被跟踪添加到暂存区。使用 git add . 命令可以将当前工作目录中的所有文件递归的添加到暂存区中,同时也可以使用git add *但是git add * 不会将子目录下的文件递归的添加到暂存区中。
记录文件修改信息

假如此时你的项目中还有一个名为benchmarks.rb的文件,并确定该文件已经被跟踪,此时对该文件做一些修改,在查看文件状态,会列出类似下列的信息

# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: benchmarks.rb
#

benchmarks.rb信息出现在Changed but not updated下面的区域中,文件名前面显示有modified的字样,说明该文件已经被修改过,但是还没有被暂存。此时你运行git add命令将修改后的benchmarks.rb提交到暂存区后,再次执行git status命令:

$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
# modified: benchmarks.rb
#

这2个文件已经全部被提交到暂存区中,此时你在执行commit命令时,这2个文件就会被全部提交到版本库中。但是注意:如果在你使用commit命令之前又一次修改了benchmarks.rb文件,此时在来看看文件状态:

$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: README
# modified: benchmarks.rb
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: benchmarks.rb
#

简写信息为:

$ git status -s
MM benchmarks.rb
A README

你会发现此时benchmarks.rb同时出现在2个状态栏中,这是为什么呢?事实上当你使用add命令时,git会将文件添加到暂存区中,commit命令是将暂存区中的内容保存到git版本库中,如果此时使用commit命令,实际上提交的将是上一次被add的文件,而不是现在已经有过第二次修改的新文件,所以在提交之前还要对该文件再次使用add命令。
忽略指定文件
有些时候你会希望git忽略掉某些你不想提交的文件,或者不想在查看文件状态时显示这些文件,例如项目中生成的临时文件以及日志文件等等,此时你就需要建立一个名为".gitignore"的文件,将你想要让git忽略的文件记录到该文件中,如:
*.[oa]    这句话告诉git将忽略所有以.o或.a结尾的文件

*~    这句话告诉git将忽略所有以~为结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
*.log 这句话告诉git将忽略所有以.log为结尾的文件

查看被暂存文件和未被暂存文件的变更信息
如果你觉得git status命令显示的信息太模糊,不能确切的显示出你想要查看的具体的修改信息,此时就可以使用 git diff命令。
默认情况下该命令会将工作目录中的文件与git仓库中的文件进行对比,这里有几个重要的选项:
  --cached  将暂存区中的文件与git仓库中的文件进行对比
  HEAD      用来查看所有状态的文件的更改信息
  --stat    显示精简信息

提交你的修改
当你修改好文件后,通过git add命令将这些文件的快照信息存入暂存区,就可以使用commit命令将文件提交到git仓库中。这里需要注意:任何你新增加的文件或者修改过的文件都不会被自动放到暂存区中,而commit命令只会提交暂存区中的文件,因此不用忘记使用add命令将文件添加到暂存区中。

 $git commit

  当执行完上面命令后,系统会为你打开一个你设定好的文件编译器(通过$EDITER环境变量设定,如果没有设定过则打开系统的默认编译器),将你需要添加的提交信息从编译器顶部开始添加,其中以‘#’开头的行将会被忽略,不会被记录进去,此外git还会将git status命令信息自动输入到该编译器中供你参考,输入好之后退出编译器,即可完成提交(注意:如果你在编译器中没有输入任何内容而直接退出,那么本次提交将会失败)。另外你也可以使用-m参数在命令中直接添加提交信息,如:$git commit -m 'My Commit'。该命令还有一个重要的参数:-a。使用该参数后可以不用使用add命令将文件添加到暂存区中,它会自动将所有改动过的被跟踪的文件全部提交,包括子文件夹中的文件也会被递归提交,但是对于新建的文件你还是需要使用git add将该文件进行跟踪后才可以提交。完成提交后系统会输出本次提交的一些简单信息。
移除文件
  如果你想将某个文件从git仓库中移除,可以使用git rm命令来实现,该命令将文件从暂存区中删除,当你下次commit后就会将该文件从git数据仓库中删除掉,需要注意的是,使用该命令后,同时会将该文件从你的工作目录中删除,可以为该命令添加一个--cached参数来防止删除工作目录中的文件,但是该文件会变为untracked状态。如果你只是简单的将文件从工作目录中删除,当你执行git status命令查看文件状态时,你会发现该文件在“change but not updateed”的区域下,此时你还是需要使用git rm命令将该文件从暂存区中删除并将其状态更改为untranked。
    同时git还支持使用通配符进行批量删除文件,例如:
      $git rm log/\*.log    此处\为转移字符,是必不可少的,该命令会删除log文件夹下的所有以.log结尾的文件
      $git rm \*~    这条命令将会删除所有以~结尾的文件。
移动文件
    不像其它版本控制器那样,git不支持文件的重命名,如果你尝试为一个文件重命名,git不会存储任何能够通知你文件有过重命名操作的信息。但是你可以使用mv命令来为文件重命名,如:
    $git mv file_from file_to
事实上,使用次条命令重命名一个文件后,查看文件状态时,系统会显示rename。

查看历史提交记录
    git log命令用来查看commit提交历史记录信息,当你在有过提交记录的git仓库中使用该命令后,系统会列出会出现类似下面这样的信息:
commit 237c9d08a266cbcf9876843152e395ff1c47336b
Author: gbyukg <gbyukg@163.com>
Date:   Thu Dec 1 14:55:21 2011 +0800

    first

默认情况下,系统会按照提交时间由大到小的顺序排列出来,其中这4行分别对应的是:
    commit的文件经过SHA-1 checksum 后所生成的40位编码
    本次提交的作者姓名以及邮箱
    提交日期
    提交时输入的信息
git log命令包含大量的复杂的选项,能够让你找出任何你想要的信息,这里介绍几个主要的参数:
    -p :它可以列出每次提交时文件所做的修改的详细信息,同时后面可以追加一个 -n(n为任意一个正整数)参数,该参数用来显示最近n次的修改信息,若n为0将不显示任何信息,如果n大于提交过的此时,则将所有提交信息全部显示出来。例:$git log -p -2    显示最近2次提交的信息。
    --stat:    它可以将提交信息简化的显示出来
    --pretty:    按照指定格式显示出日志信息,这里有一些预设好的选项可供使用:oneling、short、full和fuller等等,如:git log -pretty=oneline。但是更有趣的选项是formate,它可以让你按照自己指定的格式输出日后信息,例:$git log --pretty=format:"%h - %an , %ar : %s"。下面列出了format中的选项以及含义:
%H    commit的哈希值(SHA-1)
$h    commit的哈希值的缩写(前七位)
%T    工作树的哈希值
$t    工作树的简写哈希值
$an    项目作者姓名
$ae    项目作者e-mail
$ad    做成日期
$ar    做成日期(小时制)
$cn    提交者姓名
$ce    提交者e-mail
$cd
$cr
$s    提交注释
  --shortstat  只是将--stat命令中的changed/deletions/insertions的信息显示出来
  --name-only  显示被更改过的文件信息列表
  --name-status  显示added/modifide/deleted的文件信息
  --graph    以简单的图标形式显示你的分支和合并记录,如:$ git log --oneline --graph

获取你想要的日志信息
  git log命令中不仅包含了格式化输出日志的信息,还提供了一些限制选项,这些选项可以减少日志条数,事实上你可以直接使用-n选项,其中n是一个正整数,显示最近的n条日志记录。
  此外还有一些时间限制的选项,如--since--until,这些选项将会非常有用。例如,下面的命令将会显示过去2周内所发生的事情:  

$ git log --since=2.weeks

这条命令提供了许多预设好的格式,你可以指明一个特定的日期("2011-11-04")或者一个类似于"2 years 3 day 5 minutes ago"的格式。
  同时你也可以通过过滤将与你的查询想匹配的信息显示出来。--author 选项允许你检索出指定作者的信息,--prep 选项允许你通过搜索提交信息中的关键字来显示信息。注意:如果你想同时使用--author和--prep选项,你必须在额外的添加一个--all-match选项,否则系统只会列出符合这2个条件中的一个条件的信息
  你也可以向git传递一个路径,如果你指定了一个文件夹或文件,就可以限制系统只显示这些文件的一些变更信息,通常该选项应当被放到最后的选项中,同时应当有2个-在文件名前来将文件名从选项中分离出来。

$ git log --pretty="%h:%s" --author=gitster --sincd="2010-10-01" --before="2011-11-01" --no-merges --t

git撤销操作
更改最后一次提交:
  当你使用commit命令后发现忘记了将其它修改过的文件也一起提交到git数据仓库中,或者提交的文件需要再次修正一下才可以提交,或者在提交时输入了错误的提交信息,此时你就可是使用 $git commit --amend命令进行重新提交,这条命令会使用暂存区中的问进当作此次提交的内容,如果在上次提交过后暂存区中的内容没有发生任何变化,那么修改的只是提交信息。使用该命令后,系统会再次打开编译器,此时编译器中会显示出你上次提交是所输入的提交信息,修改过提交信息后保存退出即可。
删除暂存区中的文件
  当你使用add命令将文件添加到暂存区后,发现某些文件不需要提交,此时你希望将该文件从暂存区中删除,这是你可以使用 $git reset HEAD [file] 该命令会将指定的file将暂存区中删除,如果没有指定file,则清空暂存区。
撤销修改过的文件
  当你在工作目录中修改完成一个文件时,由于某些原因想要撤销对这些文件的修改,可以使用命令: $ git checkout filename 该命令会将文件撤销到上一次将对该文件commit时的状态。注意:该命令只能撤销没有被添加到暂存区中的文件,如果想对某个已经使用add命令添加到暂存区中文件进行撤销,需要先使用git reseat HEAD 命令将该文件从暂存区中删除。

修复已提交文件中的错误

如果你已经做了一个提交(commit),但是你马上后悔了, 这里有两种截然不同的方法去处理这个问题:

1 创建一个新的提交(commit), 在新的提交里撤消老的提交所作的修改. 这种作法在你已经把代码发布的情况下十分正确.

2 你也可以去修改你的老提交(old commit). 但是如果你已经把代码发布了,那么千万别这么做; git不会处理项目的历史会改变的情况,如果一个分支的历史被改变了那以后就不能正常的合并.

创建新提交来修复错误

创建一个新的,撤消(revert)了前期修改的提交(commit)是很容易的; 只要把出错的提交(commit)的名字(reference)做为参数传给命令: git revert就可以了; 下面这条命令就演示了如何撤消最近的一个提交:

$ git revert HEAD

这样就创建了一个撤消了上次提交(HEAD)的新提交, 你就有机会来修改新提交(new commit)里的提交注释信息.

你也可撤消更早期的修改, 下面这条命令就是撤消“上上次”(next-to-last)的提交:

$ git revert HEAD^

在这种情况下,git尝试去撤消老的提交,然后留下完整的老提交前的版本. 如果你最近的修改和要撤消的修改有重叠(overlap),那么就会被要求手工解决冲突(conflicts), 就像解决合并(merge)时出现的冲突一样.

译者注: git revert 其实不会直接创建一个提交(commit), 把撤消后的文件内容放到索引(index)里,你需要再执行git commit命令,它们才会成为真正的提交(commit).

修改提交来修复错误

如果你刚刚做了某个提交(commit), 但是你又想马上修改这个提交; git commit 现在支持一个叫--amend的参数,它能让你修改刚才的这个提交(HEAD commit). 这项机制能让你在代码发布前,添加一些新的文件或是修改你的提交注释(commit message).

如果你在老提交(older commit)里发现一个错误, 但是现在还没有发布到代码服务器上. 你可以使用 git rebase命令的交互模式, "git rebase -i"会提示你在编辑中做相关的修改. 这样其实就是让你在rebase的过程来修改提交.

 

原文地址:https://www.cnblogs.com/gbyukg/p/2271372.html