Git使用方法(二)

来源:互联网 发布:守望先锋 英雄详细数据 编辑:程序博客网 时间:2024/06/03 23:40

在Git中提交时,会保存一个提交(commit)对象,它包含一个指向暂存内容快照的指针,作者和相关附属信息,以及一定数量(也可能没有)指向

提交对象直接祖先的指针:第一次提交是没有直接祖先的,普通提交有一个祖先,由两个或多个分支合并产生的提交则有多个祖先。现在假设

工作目录下有3个文件,准备将他们暂存后提交。暂存操作会对每一个文件计算校验和(即SHA-1哈希字符串),然后把当前版本控制的文件快照

保存到Git仓库中,并将校验和加入暂存区域。当使用git commit新建一个提交对象前,Git会先计算每一个子目录(本例中就是就是项目根目录)

的校验和,然后在Git仓库中将这些目录保存为树(tree)对象。之后Git创建的提交对象(commit),除了包含相关提交信息以外,还包含着指向这

个树对象(项目根目录)的指针,如此他就可以在将来需要的时候,重现此次快照的内容。


这个是提交一次后仓库里的数据


多次提交后Git仓库数据

Git中的分支,其实本质就是个指向commit对象的可变指针。Git会使用master作为分支的默认名字。在若干次提交后,你其实已经有了一个

指向最后一次提交对象的master分支,它在每次提交的时候都会自动向前移动。



一:git branch



经过多次提交仓库中的情况如上,master指向最新的commit,那么怎样创建一个新的分支呢,可以使用git branch+分知名,这里用

git branch testing,就创建了一个基于master的分支。

$git branch testing

HEAD是一个引用,指向正在使用的分支。


进行查看:


下面切换到新的分支:


$git checkout testing


使用git branch可以查看当前都有哪些branch,前面有*的表示,当前所在的branch。


可以看到,此时master与testing都指向同一个commit,这里的9831*******,一共是20个字节,40个十六进制的字符,这个就是将文

件放到暂存区时产生的哈希字符串,它作为文件的名字,这里使用git cat-file -t 查看object的类型,这里至少用前四个字符。


现在 切换到testing分支,修改工作目录下的main.c文件,然后提交,再次看HEAD的指向,发现testing中的HEAD已经指向新的

commit了。


现在对master分支的main.c文件进行修改:



可以看到此时master指向的commit已经变化,形成上图的分支。

git branch -a 列出所有分支,包括remote和local branches

git branch -r 列出remote branches

git branch -d new-branch 删除new-branch

git branch -D new-branch 强制删除new-branch


二:git merge



从上边几张图可以看出先是基于master创建了分支iss53,此时它们指向同一个commit,之后iss32分支进行了commit,然后基

于master创建了新的分支hotfix,并进行了commit。现在要把hotfix分支合并到master分支中。


git merge + 要merge的branch,这样就可以把branch merge到当前branch上了。先git checkout master,然后git merge hotfix,

这样hotfix branch就可以merge到master分支上了,然后git branch -d hotfix对hotfix分支进行删除。这里的merge其实是比较简

单的,由于master分支指向的commit是hotfix分支指向的commit的parent,所以直接移动master指针到hotfix指向的commit就可以了。




git branch --merge查看哪些分支已被并入当前分支

git branch --no-merge查看哪些分支没有被并入当前分支



下面这个是three-way merge


这里要merge c4和c5,此时Git会用两个分支的末端(C4和C5)和他们的共同祖先(C2)进行一次简单的三方合并计算。Git可以

自己裁决哪个公共祖先才是最佳合并基础。




三:git checkout


git checkout branch-name 切换到branch-name

git checkout master 切换到master

git checkout -b new-branch master 从master建立新的new-branch,并同时切换过去new-branch

git checkout -b newbranch 由现在的分支为基础,建立新的branch

git checkout -b newbranch origin 由origin的基础,建立新的branch

git checkout filename 还原档案到Repository状态

git checkout HEAD 将所有档案都checkout出来(最后一次commit的版本),注意,若有修改的档案都会被还原到上一版

git checkout xxxx 将所有档案都checkout出来(xxxx commit的版本,xxxx是commit的编号前四位),注意,若有修改的档案

都会被还原到上一版


四:git show


可以使用git show加上commit名称来显示更详细的commit信息:


也可以使用git show加分支名称,也可显示分支信息:


使用HEAD字段可以代表当前分支的头(也就是最近一次commit):

$git show HEAD

每一次commit都会有“parent commit”,可以使用^表示parent:

$git show HEAD^ 查看HEAD的父母的信息

$git show HEAD^^ 查看HEAD的父母的父母的信息

$git show HEAD~5 查看HEAD上溯5代的信息

有的时候git merge会产生双父母,比如three-way merge的时候,这种情况这样处理:

$git show HEAD^1 查看HEAD的第一个父母

$git show HEAD^2 查看HEAD的第二个父母


五:git archive

可以把当前版本(HEAD所处的位置)给export出来

使用git describe可以查看当前的version

$mkdir ../linux-2.6.11

$git archive -v v2.6.11 | (cd ../linux-2.6.11/ && tar xf -)

$head -4 ../linux-2.6.11/Makefile


从本地git仓库中提取某个版本的kernel:

$git archive -v v2.6.11 | (cd ../linux-2.6.11/ && tar xf -)

-v表示--verbose,注意'v2.6.11'可以是git tag -l列出的tags中的一个,也可以是其他Rev ID例如HEAD等

这里的“&&”类似“;”不过是有区别的,如果每个命令被一个分号“;”所分隔,那么命令会连续的执行下去。如果每个命令

被“&&”号分隔,那么这些命令会一直执行下去,如果中间有错误的命令存在,则不再执行后面的命令,没错则执行到完为止。

这里的“-”作用是把前边的输出作为这里的输入

导出最新的kernel:

$git archive -v HEAD | (cd ../linux-HEAD/ && tar xf -)

或者打成tar包:

$git archive -v --format=tar v3.0 | bzip2 >../linux-3.0.tar.bz2

一:git remote


远程仓库是指托管在 网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写。同他人协作开发某个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自 的工作进展。管理远程仓库的工作,包括添加远程库,移除废弃的远程库,管理各式远程库分支,定义是否跟踪这些分支,等等。

在克隆完某个项目后,至少可以看到一个名为origin的远程库,Git默认使用这个名字来标识你所克隆的原始仓库:

$git remote

orgin

也可以加上-v选项(-v为-verbose的缩写,取首字母),显示对应的克隆地址:


添加远程仓库,可以指定一个简单的名字,以便将来引用,运行git remote add [shortname] [url]:



使用git remote show [remote-name]查看某个远程仓库的详细信息:


它告诉我们,运行git push时缺省推送的分支是什么(最后两行)。它还显示了有哪些远程分支还没有同步到本地(第六行的caching分支),哪些已同步到本地的远端分支在远程服务器上已被删除(Stale tracking branches下面的两个分支),以及运行git pull时将自动合并哪些分支(前4行中列出的issues和master分支)。


远程仓库的删除和重命名

可以用git remote rename命令修改某个远程仓库的简短名称,比如想把AA改成BB,可以这么运行:

$git remote AA BB

$git remote

origin

BB

移除远程仓库git remote rm命令:

$git remote rm BB

$git remote

origin


二:
git fetch


从远程仓库抓取数据,使用git fetch [remote-name][branch-name]



三:
git pull



从远程仓库分支中获得更新,git push [remote-name] [branch-name],pull命令包含两个操作:从远端分支中取出改动,然后合并到当前分支中。相当于git fetch+ git merge。

当git clone之后,直接git pull它会自动匹配一个正确的remote url,因为在.git/config文件里配置了[branch "master"]下面的内容:


 

  1. git处于master这个branch下时,默认的remote就是origin
  2. 当在master这个branch下使用指定remote和merge的git pull时,使用默认的remote和merge

 

$git pull



四:
git push


如果把本地的master分支推送到origin服务器上(),可以运行下面命令:推送数据到远程仓库使用git push [remote-name] [branch-name],

$git push origin master

只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果你在推数据前,已经有其他人推送了若干更新,那你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,并到自己的项目中,然后才可以再次推送。



五:git reset


使用git reset撤销改动,git reset HEAD^删除最近的commit,选项:

--mixed staged与commited都会清除,但是modified不会清除

--hard modified,staged,commited都会清除

--soft commited被清除,modified,staged还在

reset是将当前head的内容重置,不留任何痕迹。

Sets the current head to the specified commit and optionally resets the index and working tree to match。

git reset --hard HEAD~4

会将最新的4次提交全部重置,就像没有提交过一样。


使用--mixed选项,如果你不添加选项,默认使用的是--mixed选项:


这里的“changed but not updated”表示文件被modify,但是没有stage,你有两个选择,一个是stage,git add<file>...,另一个选择是撤销这次修改git checkout --<file>...


使用--hard选项:



使用--soft选项:


这里的“Changes to be committed”表示已经modified并且stage,但是没有commit,你可以使用git reset HEAD <file>...进行unstage,或者使用git commit进行commit。

有的时候想要修改提交信息使用git commit --amend

此命令将使用当前的暂存区快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,而所提交的文件快照和之前的一样。



这里将之前的commit信息“second”改为“this is second commit”。

在git中,除非你运行了git-gc --prune,否则历史是永远不会被擦除的,你可以随意恢复到任何历史状态。下面是一个恢复被git-reset --hard擦除了的commit的例子:

使用git-reflog查看历史:



六:git revert


git revert只是修改了commit,修改后再次提交。

git revert与git reset的区别:

 

  • git reset是还原到指定的版本上,这将扔掉指定版本之后的版本
  • git revert是提交一个新的版本将需要revert的版本的内容再反向修改回去,版本会递增,
  •  一:git tag

  • git tag列出已有的标签:


    使用特定的搜索模式列出匹配的标签:


    获得某个版本的源码:

    $mkdir ../linux-2.6.11
    $git archive -v v2.6.11 | (cd ../linux-2.6.11/ && tar xf -)
    $head -4 ../linux-2.6.11/Makefile


    git使用的标签有两种类型:轻量级的(lightweight)和含注释的(annotated)。新建含注释的标签会产生一个标签对象,而轻量级标签不会产生标签对象。

    轻量级的标签建立:

    $git tag v1.0

    这样就会给当前的commit打上v1.0这个标签。


    此时这个tag是一个引用,不是对象。

    含注释的标签建立:

    $ git tag -a [name] -m [“xxxx”]


    建立含注释的标签会产生一个标签对象:


    可以看到在创建标签后对象数增加了一个。



     

    二:git bisect


    如果一个项目到某一个版本发现一个错误,你还知道之前某个版本是好的,那么可以用git bisect来定位最先出现bug的版本。可以:

    git bisect start

    git bisect bad 现在这个版本是有bug的

    git bisect good good_commit good_commit是好的版本,你可以用tag表示,也可以用那20byte的前2个byte表示



    我的这个意思是,如果数大于等于5就是bug,这里找到了第一个大于等于5的commit。



    三:git format-patch


    git format-patch -2 -o ~/patch/

    git format-patch是用于把当前的git目录中的commit生成的patch文件,并组织成UNIX mailbox的邮件格式。--cc后指定的是邮件的抄送接收人。-2表示只处理最后两次commit


    四:git send-email


    git send-email --to xxx@xxx --to xxx@xx --cc xxx@xxx --bcc xx@xx ~/patch

    git send-email用于把刚才生成的patch文件直接以email的方式发送出去,要用这个命令需要保证正确配置了SMTP服务器的相关信息。用 git直接生成patch邮件发送到邮件列表是一个很方便的方式,而且可以保证发出来的邮件有比较统一的格式,方便别人来审阅你的patch。

    git config file
     [sendmail]
           smtpencryption = tls
    smtppass       = xxxx
    smtpserver     = smtp.gmail.com
    smptuser = kernellwp@gmail.com       
    smtpserverport = 587

原创粉丝点击