免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 19692 | 回复: 75
打印 上一主题 下一主题

linux git常见命令整理 [复制链接]

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-04-22 15:34 |只看该作者 |倒序浏览
git常见命令整理  
【基本概念】
A) git本地由三个部分组成:工作区 和 暂存区 和 本地库。
B) .git目录才是仓库的灵魂,.git目录里面包括 暂存区 和 本地库,.git目录外的地方是工作区。
C) git中包含4类对象 (commit 提交对象, tree 目录, blob 文件, tag 标记)


【git模型】
工作区 = working directory
暂存区 = snapshot/stage/index
本地库 = local repo




【.git目录】
HEAD 指向当前分支
config 项目配置文件
description 供GitWeb程序使用
hooks/ 客户端与服务端钩子脚本
info/ 忽略模式
index 暂存区域信息
objects/ 所有数据内容
refs/ 指向所有commit的指针




【git对象】
git提交便产生一个commit对象,commit对象中包含一个tree对象,tree对象中又会包含其他的tree对象或是blob对象,blob对象是最小的组成单元,即独立的文件。
每个对象都对应一个唯一的SHA-1值,只有当文件或目录有修改时这个值才会重新计算发生改变。
$ git log 可以查看所有commit对象
$ git ls-tree <commit> 查看commit对象中的tree对象
$ git show <blob> 查看blob的具体内容


【参数解释】
HEAD = HEAD~0
HEAD^ = HEAD~1
HEAD^^ = HEAD~2




【git 命令】
git init                                  // 如果仅仅在本地创建空配置库,不需要带任何参数
git init --bare                                 // 在服务器上创建一个新的空配置库,比如是在repositories/prj/Code.git目录下执行。bare repository主要是用作分享版本库。
git clone git@YOUR_SERVER:prj/Code.git    // 从远程服务器的 repositories/prj/Code.git 目录下克隆
git push                                  // 上传所有内容,从 本地库 到 服务器
git push origin master                    // 上传master分支
git push origin --tags                    // 上传本地标签
git fetch                                 // 从服务器上下载更新代码到 本地库,工作区和 暂存区 不会被改变。
git pull = git fetch + git checkout       // 下载数据到 本地库,并更新到 暂存区 和工作区
git remote


git add
git rm
git commit
git diff
git diff --cached
git checkout
git status
git show
git log




git reset
git revert


git branch
git merge
git show-branch


git config
git tag
git stash


.gitignore  需要忽略的临时文件
【举例】
*.o
obj/
.svn/




【git remote】-- 远程操作命令
git remote -v              // 显示远程库的路径
git remote add             // git remote add <name> <url>
git remote rm   
git remote show  


【git add】-- 如果你新增了文件或文件夹,那么就要老老实实的先git add .  再git commit
git add file1 file2 file3  // 将新增加文件加入到 暂存区 中
git add .                  // 所有文件全部加入到 暂存区 中,包括子目录,不包括空目录
git add -i                 // 进入交互式add,尚未体验,有空试一下


【git rm】-- git 提供相应命令 (add,rm) 将工作区变更加入到 暂存区
git rm -rf xxx
git rm xxx.file




【git commit】-- 将 暂存区 的东西加入到 本地库,(注意:这里只是提交到本地库,还需要通过 push 命令才能将本地库的内容上传到服务器)
git commit -m “something” someFile //提交指定文件
git commit -m "写上描述"           // 最常用的用法
git commit -a -m "写上描述"        // -a 参数请谨慎处理,常见的错误结果是把某些编译中间文件也加入配置库。
commit和commit -a的区别
commit -a相当于:
第一步:自动地add所有改动的代码,使得所有的开发代码都列于index file中
第二步:自动地删除那些在index file中但不在工作树中的文件
第三步:执行commit命令来提交




【git diff】
git diff SHA_AAA           // 比较工作目录和SHA_AAA之间的差异
git diff SHA_AAA..SHA_BBB  // 比较两次不同的commit之间的差异
git diff                   // 比较工作区和 暂存区 的差异。 这个命令只在git add之前使用有效,如果已经add了,那么此命令输出为空。
git diff --cached          // 比较 暂存区 和HEAD的差异。 在git add之后在git commit之前有效,如果已经commit了,那么此命令输出为空。
git diff --name-only       // 只列出不同文件的名字,而不显示具体的差异之处
git diff -stat             // 可以统计数据,比较特别的命令


【git checkout】 -- 恢复 工作区 的内容
git checkout -- test.txt   // 从 暂存区 恢复到 工作区,相当于撤销工作区中 test.txt 文件尚未提交的修改
git checkout -f            // 从 本地库 恢复到 暂存区和工作区, 强制修改工作区的内容,一般对于当前修改不满意,放弃修改后从头开始
git checkout HEAD test.txt // 从 本地库 恢复到 暂存区和工作区, 取HEAD中的这个文件test.txt
git checkout HEAD .        // 从 本地库 恢复到 暂存区和工作区, 取HEAD
git checkout $(git rev-list master -n 1 --first-parent --before=2012-03-21)
// 取master分支,2012-03-21 00:00:00 的代码, 这个命令可以帮助取没打标签的版本代码,一般对应每日构建的版本。


git checkout SHA_value     // 从 本地库 恢复到 暂存区和工作区, 取特定的commit id=SHA_value




【git status】-- 查看变化,变化包括工作区和暂存区的差异,暂存区和本地库的差异,本地库的提交记录,分支/合并的状态




【git show】
git show SHA_value         // 显示特定commit的内容
【git log】
git log --name-only        // 仅在提交信息后显示已修改的文件清单
git log --name-status      // 显示文件名以及状态(新增、修改、删除)
git log -p                 // 会输出非常详细的日志内容,包括了每次git commit之后都做了哪些源码的修改,可以看到具体的差异。
git log -2                 // 最近两次提交的日志。 -(n) 仅显示最近的n 条提交
git log --graph            // 图形化方式呈现提交记录, ASCII 图形表示
git log --stat             // 显示修改文件名以及修改统计信息(文件大小变化)
git log --raw -5           // 文件列表,文件属性
git log --grep=mouse       // 按照关键字搜索
git log --relative-date    // 使用较短的相对时间显示(比如,“2 weeks ago”)。


git log --pretty="%h:%s" --author=gke --since="2011-10-01" --before="2011-10-05" --no-merges -- t/
// 2011年10月期间,gke 提交的但未合并的测试脚本(位于项目的t/ 目录下的文件)


        --since, --after       // 仅显示指定时间之后的提交。
        --until, --before      // 仅显示指定时间之前的提交。
git log --author=g00196971 --after="2011-12-25" > 2011_12_25_gke.txt               // 查看 2011-12-25之后g00196971 的提交记录
git log --after="2011-12-09" --before="2011-12-11" > git_log_1209_1211.txt         // 查看 2011-12-09到2011-12-11 时间段内的提交记录
git log --since="1 day"     // 可以给出各种时间格式,比如说具体的某一天(“2012-01-15”),或者是多久以前(“2 years 1 day 3 minutes ago”)。
git log --pretty=oneline    // 提交记录格式 显示为一行。 可用的选项包括oneline,short,full,fuller 和format(后跟指定格式)。
git log 目录名              // 查看特定的目录的提交记录


【去除别人分支merge过来的提交记录】
git log --pretty=oneline --abbrev-commit master > master.log
git log --pretty=oneline --abbrev-commit > all.log
grep -vwFf master.log all.log > my_branch.log


【git revert和git reset的区别】
git reset   // 是撤销某次提交,但是此次之后的修改都会被退回到暂存区
git revert  // 是撤销 某一次/某中间几次 的操作,此次操作之前的commit都会被保留


1. git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。
2. 在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。
   因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是之间把某些commit在某个branch上删除,
   因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
3. git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。




【git reset】
git reset --hard SHA_value   // 销毁自己的修改, SHA_value可以从git log中查找
git reset --hard HEAD~3      // 最后三个commit(即HEAD, HEAD^和HEAD~2)提交有问题,你想永久删除这三个commit。
git reset –-mixed            // --mixed可以省略,这是默认模式。
git reset --hard HEAD


A). --soft:  暂存区 和工作区中的内容不作任何改变,仅仅把HEAD指向<commit>。这个模式下可以在不改动当前工作环境情况下,改变head指针,即切到任意commit。
B). --mixed: 这是reset的default模式。 暂存区 中的内容会变化,但是工作区中的内容不变。
C). --hard:  暂存区 和工作区中的内容都会发生改变,就像刚clone出来一样,用来做还原操作且不想保存任何修改。




【git revert】
git revert HEAD       // 撤销前一次 commit
git revert HEAD^      // 撤销前前一次 commit
git revert SHA_value  // 撤销指定的版本,撤销也会作为一次提交进行保存。


A) git revert HEAD~3:丢弃最近的三个commit,把状态恢复到最近的第四个commit,并且提交一个新的commit来记录这次改变。
B) git revert -n master~5..master~2:丢弃从最近的第五个commit(包含)到第二个(不包含),但是不自动生成commit,这个revert仅仅修改working tree和 暂存区 。






【git branch】
git branch test_branch       // 创建一个实验分支
git branch                   // 查看总共有哪些分支
git branch -r                // 参看本地分支和远程分支的映射关系
git push origin test_branch  // 把本地当前分支的改动推到服务器的新分支上, 如果 origin test_branch 不加的话,那么会默认推送本地的所有的branch
git branch -d test_branch    // 合并成功之后,可以删除实验分支了。这个动作要谨慎,确定已经合并成功,不再需要这个分支了。
git checkout [branch_name]   // 切换到实验分支
git_all.sh checkout -b test_branch origin/test_branch   // git checkout -b [分支名] [远程名]/[分支名]




【git merge】
git merge test_branch        // 从test_branch分支合并到当前分支。
                             // 如果两个分支中有相同的代码被改动,会提示冲突,需要手动修改。手动修改当前分支中的冲突内容,然后再次merge实验分支到当前分支。


【git show-branch】
git show-branch -a          // 显示本地分支
git show-branch -r          // 显示远程分支




【git config】-- 配置和查询 git 的基本信息
git config --global user.name "g00196971"
git config --global user.email guanke@huawei.com
git config --global color.ui true
git config --global core.autocrlf input
git config --global merge.tool vimdiff
git config --list            // 检查已有的配置信息


【git tag】
git tag                                           // 查询所有标签
git tag -a REL_B011 -m 'software version = B011'  // 在本地打标签
git push origin --tags                            // 一次把本地打的标签全部上传
git tag -d REL_B011                               // 删除标签
git show tag                                      // 显示tag 的详细信息,包括标签的详细描述,对应的commit SHA_value
git checkout [tagname]                            // 和切换分支一样,可以切换到标签




【git stash】-- 使用场合:当前工作区内容已被修改,但是并未完成。这时Boss来了,说前面的分支上面有一个Bug,需要立即修复。可是我又不想提交目前的修改,因为修改没有完成。
                但是,不提交的话,又没有办法checkout到前面的分支。此时用Git Stash就相当于备份工作区了。然后在Checkout过去修改,就能够达到保存当前工作区,并及时恢复的作用。
git stash:                // 备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。
git stash pop:            // 从Git栈中读取最近一次保存的内容,恢复工作区的相关内容。由于可能存在多个Stash的内容,所以用栈来管理,pop会从最近的一个stash中读取内容并恢复。
git stash list:           // 显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
git stash clear:          // 清空Git栈。此时使用gitg等图形化工具会发现,原来stash的哪些节点都消失了。
git stash apply 版本号 :  // 取出特定的版本号对应的工作空间






【参数解释】
【git回车换行问题】


用git status命令查看的时候,一些没有更改过的文件也显示为modified。checkout到某个分支,什么都不做直接git status也会出现。
按理说能checkout到别的分支去说明现在这个分支已经是干净的了(实际上也是做过提交的),再跳回来的时候未做任何改动就会出现一堆已经修改过的文件。
用diff查看文件修改都是大段大段的修改,实际上代码都一样。不得已只好暂时commit上去。发现原来是行结束符惹的祸。
格式化是许多开发人员在协作时,特别是在跨平台情况下,遇到的令人头疼的细小问题。
由于编辑器的不同或者Windows程序员在跨平台项目中的文件行尾加入了回车换行符, 一些细微的空格变化会不经意地进入大家合作的工作或提交的补丁中。


熟悉 git的配置选项就可以解决这些问题。
在Windows上是CRLF来作为一行的结束符,而Linux上则是LF作为行结束符
在git中提供了autocrlf的设置,可以用来自动转换CRLF,它可以设置成true,false,input


$ git config --global core.autocrlf true
设置为true,在checkin时,行结束符被转换为LF。在checkout时,行结束符被转换为CRLF。


$ git config --global core.autocrlf input
设置为input,在checkin时,行结束符被转换为LF,但是checkout时,则不会转换。


$ git config --global core.autocrlf false
设置为false,无论checkin还是checkout时,都取消自动转换功能。




【文档】
git_community_book.pdf
pro_git_中文版本.pdf


【工具】
Git-1.7.9-preview20120201.exe
TortoiseGit-1.7.7.0-32bit.msi


【一些好网站】
Why Git is Better than X
http://thkoch2001.github.io/whygitisbetter/



A successful Git branching model

http://nvie.com/posts/a-successful-git-branching-model/



可视化方式学习git

http://pcottle.github.io/learnGitBranching/



【附件】
一些比较好的示意图

repo的用法(zz)





注:repo只是google用Python脚本写的调用git的一个脚本,主要是用来下载、管理Android项目的软件仓库。(也就是说,他是用来管理给git管理的一个个仓库的)

下载 repo 的地址: http://android.git.kernel.org/repo ,可以用以下二者之一来下载 repo

wget http://android.git.kernel.org/repo

或者

curl http://android.git.kernel.org/repo > ~/bin/repo  

下载完成后须修改repo的权限: chmod a+x ~/bin/repo



用repo sync 在抓去 android source code 的时候,会经常出现一些错误导致 repo sync 中断,每次都要手动开始。 可以用如下的命令,来自动重复

$?=1;

while [ $? -ne 0 ] ;

do  repo sync ;

done



获取帮助:

repo help [ command ]   //显示command 的详细的帮助信息内容

示例: repo help init 来获取 repo init 的其他用法



repo init -u URL 用以在当前目录安装 repository ,会在当前目录创建一个目录 ".repo"  -u 参数指定一个URL, 从这个URL 中取得repository 的 manifest 文件。   

示例:repo init -u git://android.git.kernel.org/platform/manifest.git

获取的manifest文件放在.repo目录中。命名为manifest.xml。这个文件的内容其实就是所有被git管理的仓库的列表!



可以用 -m 参数来选择获取 repository 中的某一个特定的 manifest 文件,如果不具体指定,那么表示为默认的 namifest 文件 (default.xml)

repo init -u git://android.git.kernel.org/platform/manifest.git -m dalvik-plus.xml

(有诸多供我们选择的manifest文件,所有的manifest文件都放在目录.repo/manifests中,该目录本身亦被git所管理,你可以cd进去看看)



可以用 -b 参数来指定某个manifest 分支。

repo init -u git://android.git.kernel.org/platform/manifest.git -b release-1.0

你会发现.repo/manifests是个被git管理的仓库,这里放的是所有的manifest文件(*.xml),因为被git管理,固然有分支,-b可以切换到你想要的分支然后再下载相关的xml文件,当然具体下载那个xml还要看-m参数了,所以如果你仅仅指定-b而没有-m的话,就是下载-b指定分支下的default.xml文件

如果不指定-b参数,那么会默认使用master分支



4. repo sync [project-list]

下载最新本地工作文件,更新成功,这本地文件和repository 中的代码是一样的。 可以指定需要更新的project , 如果不指定任何参数,会同步整个所有的项目。

如果是第一次运行 repo sync , 则这个命令相当于 git clone ,会把 repository 中的所有内容都拷贝到本地。 如果不是第一次运行 repo sync , 则相当于 git remote update ;  git rebase origin/branch .  repo sync 会更新 .repo 下面的文件。 如果在merge 的过程中出现冲突, 这需要手动运行  git  rebase --continue



5. repo update[ project-list ]

上传修改的代码 ,如果你本地的代码有所修改,那么在运行 repo sync 的时候,会提示你上传修改的代码,所有修改的代码分支会上传到 Gerrit (基于web 的代码review 系统), Gerrit 受到上传的代码,会转换为一个个变更,从而可以让人们来review 修改的代码。



6. repo diff [ project-list ]

        显示提交的代码和当前工作目录代码之间的差异。



7. repo download  target revision

        下载特定的修改版本到本地, 例如:  repo download pltform/frameworks/base 1241 下载修改版本为 1241 的代码



8. repo start newbranchname .

        创建新的branch分支。 "." 代表当前工作的branch 分支。



9.  repo prune [project list]

        删除已经merge 的 project



10. repo foreach [ project-lists] -c command

       对每一个 project 运行 command 命令



12. repo forall -c

这个命令会遍历所有的git仓库,并在每个仓库执行-c所指定的命令(这个被执行的命令就不限于仅仅是git命令了,而是任何被系统支持的命令,比如:ls 、 pwd 、cp 等等的 )

当我想通过这个命令遍历所有的仓库并在每个仓库执行"git checkout . "用以将每个仓库的改动都清除的时候,我这么输入命令:

repo forall -c git checkout .

我发现这样根本不行。看来repo不能遍历执行checkout这个命令。今天我终于想到了另外一个命令"git reset --hard HEAD" 哈哈

repo forall -c git reset --hard HEAD


再说一个新发现:以前用repo forall 执行一些命令的时候,可能再遍历到某个仓库的时候出了问题,但是我却苦于不知道这个仓库到底是哪个!一直也没有解决。今天终于找到了。。。。  关键时候还是要看命令自己带的帮助手册呀。。。

repo help forall  用这个命令查看下针对forall的帮助吧。说的很清楚,repo执行的时候加上-p参数就可以在遍历到每个仓库的时候先打印出当前的pwd,然后再继续执行-c所指定的命令。举例如下:


repo forall -p -c git branch   



//该命令会遍历所有仓库并打印每个仓库的分支情况,由于有了-p参数,这样便会打印出每个仓库的路径!!!



11. repo status

       显示 project 中每个仓库的状态,并打印仓库名称。



201111071237 更新

yasin.lee.x

———————————————————————————————————————————————————————
cpp@cpp:~$ repo
Traceback (most recent call last):
  File "/home/cpp/bin/repo", line 91, in ?
    import readline
ImportError: No module named readline
cpp@cpp:~$
———————————————————————————————————————————————————————
系统里明明有readline,可是repo脚本却无法导入,后来查到应该是python安装导致的错误,应该在python编译时加上关于readline的编译选项,应该按照如下操作安装python
首先安装readline软件包:
sudo apt-get install libreadline5-dev
sudo apt-get install zlib1g-dev
然后下载python源码进入python源码目录,编译并安装python:
1. make distclean
2. ./configure  --enable-readline  BASECFLAGS=-U_FORTIFY_SOURCE
3. make -j4
4. sudo make install
注意,我同时发现在python-2.4.3版本是支持该编译选项的,而在3.1.3版本中是不能识别这个--enable-readline编译参数的。所以我目前使用2.4.3版本
repo的命令集学习

repo子命令实际上是对GIT命令的封装。所有的repo命令都可以通过repo help <command>来获取帮助



1、repo init

repo init主要完成检出清单版本库,以及配置git用户的用户名和邮件地址的工作

如repo init -u ssh://android.huawei.com/platform/manifest.git -b hw/qcom/platform --no-repo-verify --repo-branch=stable

2、repo sync

repo sync用于参照清单文件克隆或同步版本库,相当于执行git clone,如果项目版本库已存在,则相当于执行了如下的二个命令:git remote update和git rebase origin/branch。

3、repo start

repo start实际上是对git checkout -b命令的封装,创建的分支应用到所有的项目库时,需使用--all参数。

如repo start hw/qcom/platform -all

4、repo status

repo status实际上是对git diff-index、git diff-files命令的封装,同时显示暂存区和本地修改文件的差异。

如:repo status repo/ti

5、repo checkout

repo checkout是对git checkout命令的封装,检出之间由repo start创建的分支。

如:repo checkout  hw/qcom/platform  repo/ti

6、repo branches

用于读取所有项目中的分支列表并汇总显示,该命令实际上通过读取.git/refs目录下的引用来获取分支列表,以及分支的发布状态信息等

如:repo branches repo/ti

7、repo diff

repo diff是对git diff的封装,用于分别显示各个项目工作区下的文件差异

8、repo stage

repo stage实际是对git add --interactive命令的封装,用于挑选各个项目工作区中的改动以加入暂存区中

如:reop stage -i repo/ti

9、repo upload

repo upload相当于git push,但repo upload不是将版本库的改动推送到克隆时的远程服务器,而是推送到代码审查服务器gerrit中,推送的数据传输使用的是SSH协议。

10、repo download

repo ownload用户代码的审核者下载和评估提交过来的修改文件内容,即上述通过repo upload过来的内容。

11、repo rebase

repo rebase是对git rebase命令的封装,该命令的参数加上-i时,只对当前的这个项目才生效。

12、repo prune

repo prune是对git branch -d命令的封装,该命令用于扫描项目的各个分支,并删除已经合并的分支。

13、repo forall

迭代器,可以对repo管理的项目进行迭代,可以将本机中所有的仓都一并执行相关git xxx的命令。

repo forall -c "git commit -m "commit new feature into project A""

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
2 [报告]
发表于 2014-04-24 10:14 |只看该作者
CI引入git仓库存储测试用例和测试框架。多个git仓库通过repo来管理。
注: 所有开发工作请在本地分支执行,需要提交的时候请先切换分支同步主干代码

要求:修改完一个问题单就将该问题单提交到本地,然后上传代码,具体操作请按照下面提到的代码操作流程。
[]:表示可选参数,最好带有参数,逐仓使用
projectname;git库中.git/config文件中remote标签里包含的peojectname值

经典命令分不同场景收集如下   
  [ 回目录 ]一.             下载同步代码   
1.       用repo初始化所有代码:

repo init -u ssh://shgit/git/android/platform/manifest.git -b branch_name --repo-url ssh://shgit/git/android/tools/repo.git

2.       用git克隆代码仓库

git clone git://…  (ssh:// shgit.marvell.com/git/android/…)

3.       用repo同步某个project

repo sync ./  = git fetch shgit + git rebase shgit/mrvl-gingerbread

4.       获取更新代码(尽量少用,因为是merge):

git pull = git fetch shgit + git merge shgit/mrvl-gingerbread

5.       衍合(尽量使用rebase)

git rebase shgit/mrvl-gingerbread

6.       当需要手动rebase或merge时:

git mergetool  (一般使用kdiff)

7.       挑拣(选择需要的commit放到你的branch上):

git cherry-pick sha

  [ 回目录 ]   
  [ 回目录 ]二.             检查代码库   
1.       检查代码状态:

git status

2.       检查变动:

git diff <commit1> <commit2>

3.       查看Log:

git log

4.       查看具体文件:

git blame file

5.       查看分支信息:

git branch  git branch -a

6.       查看远程git信息:

git remote show shgit

7.       显示tag信息, 打tag:

git tag -l  git tag foo



  [ 回目录 ]三.             代码提交或撤销   
1.       提交: -a 跳过暂存区;--amend 合并前次提交

git commit -s -m “messge” -a --amend

2.       Push到仓库:

git push ssh_server your_branch[:branch_on_ssh_server]

git push ssh://yjque@shgit.marvell.com:29418/project-name.git HEAD:refs/for/branch-name

3.       增加,移动,删除文件

git add file; git mv oldfile new file; git rm file

4.       用当前暂存区取消当前最后一次提交

git commit --amend

5.       取消暂存区文件

git reset HEAD <file> --hard  (HEAD^ HEAD^^… or commit sha)

6.       Revert某个提交

git revert commit_sha



  [ 回目录 ]四.             管理branch   
1.       创建branch

git branch target_branch  src_branch

2.       删除branch

git branch -D target_branch

3.       切换branch

git checkout target_branch

4.       创建并切换到branch

git checkout -b new src_branch

5.       合并branch(少用)

git merge src_branch



  [ 回目录 ]五.       管理Patch   
1.       格式化生成PatchA:

git format-patch START_COMMIT -n (from commit no. )

git format-patch -n  (from latest)

2.       用AM打PatchA:

git am patchA

3.       用diff生成patch:

git diff > patchB

4.       打用diff生成的Patch:

git apply patchB






--------------------------------------------------------------------------------


  [ 回目录 ]常用git命令   
•同步主干代码:    repo sync [projectname]
•创建本地分支:    git checkout -b branchname
•切换分支:        git checkout branchname
•将主干分支更新合并到本地开发: git rebase remote branchname
•添加修改到缓存:  git add [-A] [filepath...]
•提交修改到本地库:git commit
•补充提交到最新的修改: git commit --amend
•撤销修改:        git checkout filepath
•删除增加:        git rm filepath      请谨慎使用,除非迫不得已,不建议使用
•查看提交记录:    git log [--oneline]
•将本地提交上传到主干: repo upload [projectname]


--------------------------------------------------------------------------------



  [ 回目录 ]正确的代码操作流程   



  [ 回目录 ]获得最新代码:   
git checkout remote
repo sync
git rebase remote branchname
if(冲突){
解决冲突
git add
git rebase --continue

}



--------------------------------------------------------------------------------



  [ 回目录 ]进行开发:   
代码开发
git add

git commit



--------------------------------------------------------------------------------



  [ 回目录 ]上传提交:   
git checkout remote
repo sync
git rebase remote branchname
if(冲突){
解决冲突
git add
git rebase --continue
}
git rebase branchname remote

repo upload projectname



--------------------------------------------------------------------------------
  [ 回目录 ] 服务器版本下载:   
repo init -u git@192.168.1.11:i700t_60501010/platform/manifest.git -b froyo_almond -m M76XXTSNCJNLYA60501010.xml

repo sync

repo forall -c git checkout --track origin/i700t_60501010 -b [你的本地分支]

或者:

git clone git@192.168.1.11:6120_gingerbread/Arm9-6120.git

git checkout --track origin/arm9_6120 -b [你的本地分支名]



  [ 回目录 ]服务器新加仓库同步:   
请按如下步骤取得Lanucher_wpon的代码:

1:~> cd I700T/.repo/manifest

2: I700T/.repo/manifest> git pull --rebase

3: I700T/.repo/manifest> cd ../..

4: I700T> repo sync platform/packages/apps/Launcher_wpon

5:I700T> cd packages/apps/Launcher_wpon

6:I700T/packages/apps/Launcher_wpon>

7:git checkout --track origin/froyo_almond -b [你的本地分支]



  [ 回目录 ]上传本地修改到服务器   
repo forall -c git pull --rebase        和服务器同步(要上传代码前,一般先进行此操作)

git add .    或git add 文件名            添加当前仓库修改的文件

git commit -m "..."                       在引号中添加你的修改记录

git push origin  本地分支名:froyo_almond       上传本地修改的代码




--------------------------------------------------------------------------------


  [ 回目录 ] 设置一些默认的全局变量,对所有工程代码有效   
git config --global user.name yourmail

git config --global user.email yourmail

git config --global push.default tracking     这样后续git push 后面不用带参数



  [ 回目录 ]查看修改记录   
git log                       本地仓库修改记录

repo forall -c git log --since="2011-04-19" --until="2011-04-21"   按条件查看工程所有仓库修改记录

repo status                查看工程中所有仓库的修改状态(包括文件位置)

git status                   查看仓库修改状态



  [ 回目录 ]分支相关   
git branch                 查看本地branch

git branch -r              查看远程branch

git branch -a              查看所有branch

git branch -D  (-d)  (branch name)    删除branch

cat .git/config      可以查看本地branch一些信息



  [ 回目录 ] 修改恢复相关   
git checkout filename1  filename2  ...           取消本地修改,和服务器同步

git stash  

git stash apply          先stash本地修改,然后执行git pull --rebase同步,最后再APPLY恢复自己的修改

git reset --soft head_commit  恢复到最后一次commit,保持代码修改

git reset --hard commit    恢复到指定一次commit,放弃之前所有修改

#回退a.py这个文件的版本到上一个版本  

git reset HEAD^ a.py

git reset commitNO filename



  [ 回目录 ]本地某仓库出问题了,不好闹腾时,删除之,并重新同步跟踪   
project_folder/vendor/qcom$ rm -rf proprietary/                         进到相应目录,删除之

project_folde$ repo sync platform/vendor/qcom/proprietary       重新repo sync,后面路径名称可查看:

                                                                                                 gedit .repo/manifest.xml

git branch -a    ----列举所有BRANCH

git branch -D 700_arm11_server

git branch -D 700_arm11_server_wifi  --删掉所有本地branch

git checkout --track origin/froyo_almond -b 700_arm11_server   然后track远程branch,重新创建本地分支



  [ 回目录 ]tag的使用   
git tag [tag_name] [version],在对应版本上(一般用change的SHA1),创建tag

git tag -l 列出当前tag

git tag -d [tag_name] 删除tag

有了tag以后,可以使用git checkout [tag_name] -b [branch_name]来检出对应tag时刻的代码。也可以用tag name来实现diff等功能。



  [ 回目录 ] patch的使用   
git diff filename1 filename2 ...                  修改位置对比,查看源码

git diff > xxx.patch                                  将修改的地方打成一个patch

git apply xxx.patch                                  将patch打上



  [ 回目录 ]后续有用到的命令继续添加   
git revert 是撤销某次提交。git reset –hard,才是退回到以前的版本

git reset --soft commitNum      保存代码修改的reset,但这个时候无法使用git diff 进行比较修改的文件,必须:

git reset filename filename     这样就可以git diff查看

git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9 b8e7b00c02b95b320f14b625663fdecf2d63e74c 查看某两个版本之间的差异

git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9:filename b8e7b00c02b95b320f14b625663fdecf2d63e74c:filename 查看某两个版本的某个文件之间的差异

  Git 命令别名

$ git config –global alias.co checkout // co将会成为checkout的别名

$ git config –global alias.br branch

$ git config –global alias.ci commit

$ git config –global alias.st status

$ git config –global user.name “username”

$ git config –global user.email username@mail.com



  [ 回目录 ] gitk使用   
gitk & 可以让终端继续编写执行命令

gitk  文件名     可以查看某个文件的修改记录



--------------------------------------------------------------------------------










--------------------------------------------------------------------------------

  [ 回目录 ]参考资料:   

1:http://blog.csdn.net/big_ant/article/details/6338990

2:http://blog.csdn.net/snowgeneral/article/details/6886933


论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
3 [报告]
发表于 2014-04-29 10:50 |只看该作者
本帖最后由 compare2000 于 2014-05-05 15:12 编辑

如何在C程序中调用dll连接库里面的函数

#define DllImport    __declspec( dllexport )
#else
#define DllImport    __declspec( dllimport )
#endif
#define DllExport    __declspec( dllexport )
#else
#define DllImport
#define DllExport
#endif

#if defined(__STDC__) || defined(WIN32) || defined (hpux)
#define dsproto(x) x
#else
#define dsproto(x) ()
#endif

DllImport int DSServerMessage(const char *MsgIdStr, const char *DefMsg, const char *Prms[10], char *pMessage, int SizeMessage);
DllImport int DSCloseJob dsproto((DSJOB));



删所有文件
#!/bin/bash
count=0
SCANFILE()
{
local dir
local FILES
dir=$1
cd ${dir}
for FILES in `ls -l | awk '{print $8}'`
do

#屏蔽掉当前目录和上一级目录以及.svn,便于遍历#
if [ "." = "${FILES}" -o ".." = "${FILES}" -o ".svn" = "${FILES}" ]
then
  echo "the file is ${FILES}"
  continue
fi
#如果是目录进入并且遍历E
if [ -d ${FILES} ]
then
  pwd
  SCANFILE ${FILES}
  continue
fi

##前面排除掉目录,剩下的就是文件,不能使用-f来判断是否是常规文件,因为有可能是link文件
echo "`pwd`/${FILES}"
rm -rf ${FILES}
done
#返回上一级目录,因为FILES只是一文件名,不是一个绝对路径,所以需要返回上一级目录n
cd ..
return 0
}
PROJECT_DIR="/global/Binary/external/internal"
#递归删除所有二进制自研文件,里面不能存放任何非自研文件,因为所有文件都会删除。?
SCANFILE ${PROJECT_DIR}
echo "clean success!"

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
4 [报告]
发表于 2014-05-15 11:38 |只看该作者
Git 常用命令总结
符号约定
[]:可选     <>:必选


git 配置
git config [--global] user.name <name>        设置用户名

git config [--global] user.email <email>         设置邮箱

git config [--global] core.editor <editor>        设置编辑器

git config [--global] github.user <user>         设置github帐号名

git config [--global] github.token <token>        设置github的token

--global是对当前系统用户的全局设置,在~/.gitconfig中。对系统所有用户进行配置,/etc/gitconfig。对当前项目,.git/config


git创建库
git clone <url>                   ssh/http(s)/git三种协议,ssh和https可推送

git init                        初始化Git仓库


git日常操作
git add <file>                 将文件加入index file

git rm [--cached]                删除,加--cached表示仅从index file中删除文件,即放弃跟踪

git mv <src> <dest>             移动/更名

git diff --cached/--staged          当前索引与上次提交(有哪些需要commit)

git diff                      当前索引与工作目录(有哪些需要add)

git diff HEAD[^]               工作目录与上次提交(当前目录与上次提交有何改变)

git commit [-a] -m <msg>          提交

git commit --amend [-m <msg>]       修复上次提交

git reset HEAD <file>             同--mixed,default option

git reset --mixed HEAD            撤销 commit 和index file,只保留 working tree 的信息

git reset --hard HEAD[^]           将 working tree 和 index file 都撤销到以前状态

git reset --soft HEAD[^]            只撤销 commit,而保留 working tree 和 index file 的信息

                     回复到某个状态。以git reset --soft HEAD为例,commit回退到

                     HEAD(相当于无变化),若是HEAD^,则commit回退到HEAD^

git gc                     用垃圾回收机制清除由于 reset 而造成的垃圾代码

git status                  显示当前工作目录状态

git log [-p]                   显示提交历史(many useful options to be learned)

git branch [branch]               显示/新建分支

git branch -d/-D               删除分支(d表示“在分支合并后删除分支”,D表示无论如何都删除分支)

git show-branch

git checkout <branch>            切换分支(分支未commit无法切换)

git merge <branch>              合并分支

git merge == git pull .

git show <branch | commit | tag | etc>        显示对应对象的信息

git grep <rep> [object]             (在指定对象(历史记录)中)搜索        

git cat-file                    查看数据

git cat-file <-t | -s | -e | -p | (type)> <object>        type can be one of: blob, tree, commit, tag

git ls-files [--stage]              show information about files in the index and the working tree(实际是查看索引文件)

git watchchanged <since>..<until>       显示两个commit(当然也可以是branch)的区别

git remote [-v]                    显示远程仓库,加-v选项可显示仓库地址

git remote add <repo_name> <url>         添加远程仓库,repo_name为shortname,指代仓库地址

git remote rename <old_name> <new_name>    更名

git remote rm <repo_name>            删除远程仓库

git remote show <repo_name>          查看远程仓库信息

git remote fetch <repo_name>           从远程仓库抓取数据(并不合并)

git pull <repo_name> <branch_name>      拉去数据并合并到当前分支

git push <repo_name> <branch_name>      推送指定分支到指定仓库  例如: git push origin HEAD:refs/for/master

git fetch <repo_name> <branch_name>[:<local_branch_name>]    拉去数据,未合并


git相关环境变量
GIT_DIR: 如果指定了那么git init将会在GIT_DIR指定的目录下创建版本库

GIT_OBJECT_DIRECTORY: 用来指示对象存储目录的路径。即原来$GIT_DIR/objects下的文件会置于该变量指定的路径下


git常见变量
HEAD: 表示最近一次的 commit。

MERGE_HEAD: 如果是 merge 产生的 commit,那么它表示除 HEAD 之外的另一个父母分支。

FETCH_HEAD: 使用 git-fetch 获得的 object 和 ref 的信息都存储在这里,这些信息是为日后 git-merge 准备的。

HEAD^: 表示 HEAD 父母的信息

HEAD^^: 表示 HEAD 父母的父母的信息

HEAD~4: 表示 HEAD 上溯四代的信息

HEAD^1: 表示 HEAD 的第一个父母的信息

HEAD^2: 表示 HEAD 的第二个父母的信息

COMMIT_EDITMSG: 最后一次 commit 时的提交信息。



常用基本概念说明
1. Working Directory(工作目录)
Git的工作目录是保存当前正在工作的文件所在的目录,和working tree是相同的意思。在这个目录中的文件可能会在切换branch时被GIT删除或者替换。这个目录是个临时目录,临时存储你从GIT库中取出的文件,这些文件一直会被保存,直到下次提交。


2. GIT Directory(GIT库目录)
项目的所有历史提交都被保存在了GIT库目录中,只要你不作回滚操作,它应该不会丢失。


3. GIT Index(Git索引)
Git index 可以看作是工作目录和Git库目录之间的暂存区,和staging area是相同的意思。可以使用Git index构建一组你准备一起提交的改变。Git Index和Git Staging area是同一个意思,都是指已经被add的但尚未commit的那些内容所在的区域。最简单的查看目前什么内容在index中的方法是使用git status命令。

•命令中”Changes to be committed“中所列的内容是在Index中的内容,commit之后进入Git Directory。
•命令中“Changed but not updated”中所列的内容是在Working Directory中的内容,add之后将进入Index。
•命令中“Untracked files”中所列的内容是尚未被Git跟踪的内容,add之后进入Index。
哪些操作能够改变git index中的内容?
A). git add <path>...会将working directory中的内容添加进入git index。
B). git reset HEAD <path>...会将git index中path内容删除,重新放回working directory中






git reset用法小结


•reset命令的三种方式:
git reset -mixed:为默认方式,不带任何参数的git reset,即时这种方式,它退回到某一个版本,只保留源码,回退commit和index的消息,如果需要提交
                          就需要先git add 再git commit 或者直接git commit -a


git reset -soft :回退到某一个版本,只回退了commit信息,不会恢复到index file一级, 如果需要提供则直接git commit 即可


git rest -hard: 彻底回退到某个版本,本地的源码也会变为上一个版本的内容




•实例
       git reset HEAD^ 回退所有内容到上一版本


git reset HEAD^  test.cpp 回退文件text.cpp到上一个版本


git reset -soft HEAD~3 向前回退到第3个版本


git reset -hard origin/master 将本地状态回退到和远程的一样


git reset 055d 回退到某一个版本(055d)


git revert HEAD 回退到上一次提交的状态,按照某一次的commit完全反向进行的一次commit


git reset -hard base 111 本地仓库回退到某一个版本

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
5 [报告]
发表于 2014-05-15 11:38 |只看该作者
Repo和Git 版本管理常用命令总结  1. 服务器版本下载:

repo init -u git@192.168.1.11:i700t_60501010/platform/manifest.git -b froyo_almond -m M76XXTSNCJNLYA60501010.xml

repo sync

repo forall -c git checkout --track origin/i700t_60501010 -b [你的本地分支]

或者:

git clone git@192.168.1.11:6120_gingerbread/Arm9-6120.git

git checkout --track origin/arm9_6120 -b [你的本地分支名]



2. 服务器新加仓库同步:

请按如下步骤取得Lanucher_wpon的代码:

1:~> cd I700T/.repo/manifest

2: I700T/.repo/manifest> git pull --rebase

3: I700T/.repo/manifest> cd ../..

4: I700T> repo sync platform/packages/apps/Launcher_wpon

5:I700T> cd packages/apps/Launcher_wpon

6:I700T/packages/apps/Launcher_wpon>

7:git checkout --track origin/froyo_almond -b [你的本地分支]



3. 上传本地修改到服务器

repo forall -c git add .

repo forall -c git reset --hard

repo forall -c git pull --rebase        和服务器同步(要上传代码前,一般先进行此操作)

git add .    或git add 文件名            添加当前仓库修改的文件

git commit -m "..."                       在引号中添加你的修改记录

git push origin  本地分支名:froyo_almond       上传本地修改的代码



4. 设置一些默认的全局变量,对所有工程代码有效

git config --global user.name yourmail

git config --global user.email yourmail

git config --global push.default tracking     这样后续git push 后面不用带参数



5.查看修改记录

git log                       本地仓库修改记录

repo forall -c git log --since="2011-04-19" --until="2011-04-21"   按条件查看工程所有仓库修改记录

repo status                查看工程中所有仓库的修改状态(包括文件位置)

git status                   查看仓库修改状态



6. 分支相关

git branch                 查看本地branch

git branch -r              查看远程branch

git branch -a              查看所有branch

git branch -D  (-d)  (branch name)    删除branch

cat .git/config      可以查看本地branch一些信息



7. 修改恢复相关

git checkout filename1  filename2  ...           取消本地修改,和服务器同步

git stash  

git stash apply          先stash本地修改,然后执行git pull --rebase同步,最后再APPLY恢复自己的修改

git reset --soft head_commit  恢复到最后一次commit,保持代码修改

git reset --hard commit    恢复到指定一次commit,放弃之前所有修改

#回退a.py这个文件的版本到上一个版本  

git reset HEAD^ a.py

git reset commitNO filename



8. 本地某仓库出问题了,不好闹腾时,删除之,并重新同步跟踪

project_folder/vendor/qcom$ rm -rf proprietary/                         进到相应目录,删除之

project_folde$ repo sync platform/vendor/qcom/proprietary       重新repo sync,后面路径名称可查看:

                                                                                                 gedit .repo/manifest.xml

git branch -a    ----列举所有BRANCH

git branch -D 700_arm11_server

git branch -D 700_arm11_server_wifi  --删掉所有本地branch

git checkout --track origin/froyo_almond -b 700_arm11_server   然后track远程branch,重新创建本地分支



9.tag的使用

git tag [tag_name] [version],在对应版本上(一般用change的SHA1),创建tag

git tag -l 列出当前tag

git tag -d [tag_name] 删除tag

有了tag以后,可以使用git checkout [tag_name] -b [branch_name]来检出对应tag时刻的代码。也可以用tag name来实现diff等功能。



10. patch的使用

git diff filename1 filename2 ...                  修改位置对比,查看源码

git diff > xxx.patch                                  将修改的地方打成一个patch

git apply xxx.patch                                  将patch打上



11. 后续有用到的命令继续添加

git revert 是撤销某次提交。git reset –hard,才是退回到以前的版本

git reset --soft commitNum      保存代码修改的reset,但这个时候无法使用git diff 进行比较修改的文件,必须:

git reset filename filename     这样就可以git diff查看

git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9 b8e7b00c02b95b320f14b625663fdecf2d63e74c 查看某两个版本之间的差异

git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9:filename b8e7b00c02b95b320f14b625663fdecf2d63e74c:filename 查看某两个版本的某个文件之间的差异

  Git 命令别名

$ git config –global alias.co checkout // co将会成为checkout的别名

$ git config –global alias.br branch

$ git config –global alias.ci commit

$ git config –global alias.st status

$ git config –global user.name “username”

$ git config –global user.email username@mail.com




12. gitk使用

gitk & 可以让终端继续编写执行命令

gitk  文件名     可以查看某个文件的修改记录

gitk -50  ubuntu64位打开gitk会导致机子变卡,后面带数字可解决此问题




13 如何添加之前没有跟踪的文件

     比如kernel中要添加bin文件:打开这个库的.gitignore文件,然后删掉 bin 不跟踪,然后就可以git add bin

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
6 [报告]
发表于 2014-05-15 11:40 |只看该作者
Repo和Git 版本管理常用命令  一、服务器版本下载:

       repo init -u git@192.168.1.11:i700t_60501010/platform/manifest.git -b froyo_almond -m M76XXTSNCJNLYA60501010.xml

       repo sync

       repo forall -c git checkout --track origin/i700t_60501010 -b [你的本地分支]

       或者:

       git clone git@192.168.1.11:6120_gingerbread/Arm9-6120.git

       git checkout --track origin/arm9_6120 -b [你的本地分支名]

====================================================================================================================================


二、服务器新加仓库同步:

       请按如下步骤取得Lanucher_wpon的代码:

       1.~> cd I700T/.repo/manifest

       2. I700T/.repo/manifest> git pull --rebase

       3. I700T/.repo/manifest> cd ../..

       4. I700T> repo sync platform/packages/apps/Launcher_wpon

       5.I700T> cd packages/apps/Launcher_wpon

       6.I700T/packages/apps/Launcher_wpon>

       7.git checkout --track origin/froyo_almond -b [你的本地分支]

====================================================================================================================

三、上传本地修改到服务器

       repo forall -c git pull --rebase        和服务器同步(要上传代码前,一般先进行此操作)

       git add .    或git add 文件名            添加当前仓库修改的文件

       git commit -m "..."                       在引号中添加你的修改记录

       git push origin  本地分支名:froyo_almond       上传本地修改的代码

====================================================================================================================

四、设置一些默认的全局变量,对所有工程代码有效

       git config --global user.name yourmail

       git config --global user.email yourmail

       git config --global push.default tracking     这样后续git push 后面不用带参数

====================================================================================================================

五、查看修改记录

       git log                       本地仓库修改记录

       repo forall -c git log --since="2011-04-19" --until="2011-04-21"   按条件查看工程所有仓库修改记录

       repo status                查看工程中所有仓库的修改状态(包括文件位置)

       git status                   查看仓库修改状态

====================================================================================================================

六、分支相关

       git branch                 查看本地branch

       git branch -r              查看远程branch

       git branch -a              查看所有branch

       git branch -D  (-d)  (branch name)    删除branch

       cat .git/config      可以查看本地branch一些信息

====================================================================================================================

七、修改恢复相关

       git checkout filename1  filename2  ...           取消本地修改,和服务器同步

       git stash  

       git stash apply          先stash本地修改,然后执行git pull --rebase同步,最后再APPLY恢复自己的修改

       git reset --soft head_commit  恢复到最后一次commit,保持代码修改

       git reset --hard commit    恢复到指定一次commit,放弃之前所有修改

       #回退a.py这个文件的版本到上一个版本  

       git reset HEAD^ a.py

       git reset commitNO filename

====================================================================================================================

八、本地某仓库出问题了,不好闹腾时,删除之,并重新同步跟踪

       project_folder/vendor/qcom$ rm -rf proprietary/                         进到相应目录,删除之

       project_folde$ repo sync platform/vendor/qcom/proprietary       重新repo sync,后面路径名称可查看:gedit .repo/manifest.xml

       git branch -a    ----列举所有BRANCH

       git branch -D 700_arm11_server

       git branch -D 700_arm11_server_wifi  --删掉所有本地branch

       git checkout --track origin/froyo_almond -b 700_arm11_server   然后track远程branch,重新创建本地分支

====================================================================================================================

九、tag的使用

       git tag [tag_name] [version],在对应版本上(一般用change的SHA1),创建tag

       git tag -l 列出当前tag

       git tag -d [tag_name] 删除tag

       有了tag以后,可以使用git checkout [tag_name] -b [branch_name]来检出对应tag时刻的代码。也可以用tag name来实现diff等功能
====================================================================================================================

十、patch的使用

       git diff filename1 filename2 ...                修改位置对比,查看源码

       git diff > xxx.patch                                  将修改的地方打成一个patch

       git apply xxx.patch                                 将patch打上

====================================================================================================================

十一、后续有用到的命令继续添加

       git revert 是撤销某次提交。git reset –hard,才是退回到以前的版本

       git reset --soft commitNum      保存代码修改的reset,但这个时候无法使用git diff 进行比较修改的文件,必须:

       git reset filename filename     这样就可以git diff查看

       git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9 b8e7b00c02b95b320f14b625663fdecf2d63e74c 查看某两个版本之间的差异

       git diff ffd98b291e0caa6c33575c1ef465eae661ce40c9:filename b8e7b00c02b95b320f14b625663fdecf2d63e74c:filename 查看某两个版本的          某个文件之间的差异

       Git 命令别名

       $ git config –global alias.co checkout // co将会成为checkout的别名

       $ git config –global alias.br branch

       $ git config –global alias.ci commit

       $ git config –global alias.st status

       $ git config –global user.name “username”

       $ git config –global user.email username@mail.com

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
7 [报告]
发表于 2014-05-15 15:02 |只看该作者
git repo使用心得
git是相当与svn,cvs等的版本控制工具,repo封装了对git的操作,使git命令更简单化,
git学习网站这是之前自己看的,但实际工作操作中还是遇到了很多困难,总是遇到冲突,无法提交等问题,现在对Git的使用还是不很熟,但现在对使用也基本了解了,这样简单介绍一下。
在使用git时,用了repo,Windows下开发,使用的是Cygwin工具,这个比git的bash更好使用。使用git一定要明白,add,commit操作都不会影像远程代码仓库,只有push了才会将代码推送到远程仓库,比svn多了一步;下面以本人的操作为例:
1. mkdir gitlearn
2.cd gitlearn
3.repo init -u ssh://xxx -m xxx.xml 拉取远程代码
这个其实就相当于git的这两部操作:
git init
git clone git@github.com:wufengxyz/hellogit.git <mailto:git@github.com:wufengxyz/hellogit.git> 这个是我在github上的一个仓库,这个网站也提供学习git的指南
4.repo start xxx <project..> 创建分支,在project工程上,可以是多个工程,这些工程是自己将要修改的,在Git使用中一定要开分支,不然冲突了就无法解决,
这个相当与git branch XXX(分支名 ) git checkout XXX,创建分支,切换到这个分支(repo可以操作多个工程、模块,而git是单工程的)
5.进入一个开了分支的工程,git branch -a,查看是否在分支上
6.git status,一定要多用次命令,查看修改等状态
7.开始在分支上修改,添加操作等等操作
8.修改过了代码,接下来使用
git add .
git commit -m "bug修复"
9.接下来可以同步远程代码了
repo sync xxx(工程名)
10.现在远程代码已经被down下来了,相信大家都只要会有冲突出现可能
有冲突修改,修改后使用git rebase --continue这样就相当于把这些修改合并到了上次冲突的提交中了
11.repo upload    这步操作是将代码推送到远程代码审核仓库,我们的leader会review我们的代码,通过了这次开发任务完成,不通过继续修改
12.review不通过要执行以下操作,这里要注意,我们的代码已经提交到远程仓库了,这是跟git rebase操作的一个区别
修改不通过的代码......修改完成后,git add .,git commit -m "xxx"完成一次commit了,接下来使用
git rebase -i HEAD~2
弹出一个界面
pick 0b92779 Test commit two
pick 9d80074 rebase test
合并两次pick,将第二个pick改为s,如下
pick 0b92779 Test commit two
s 9d80074 rebase test
esc :wq保存变更
弹出一个界面,删除后面一个Change-Id(dd操作,删除整行)
esc:wq保存变更
然后repo upload上传修改后的代码就完成了所有提交过程了,完全通过后就进行一次repo sync同步一下远程仓库代码,记住要经常用git status,或者repo status命令,每次做修改前一定要有第4步操作。
接下来介绍如果git完全不能提交使用了情况下的解决办法,经常因为没开分支造成;
把自己修改后的代码先备份出来,接下来repo sync把远程代码库中最新的代码同步下来,然后用备份的代码覆盖这些最新代码,如此操作后使用git status就会发现自己修改了的代码,然后在IDE工程中看与远程最新版本代码有什么不同,把远程代码中有,而自己当前代码中没有的加上,然后进行正常的提交过程就OK了,为什么这样大家想想就明白了相当于在最新版本代码上做了修改。
这些只是Git中最基本的操作流程,希望对刚刚使用git的同学有所帮助

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
8 [报告]
发表于 2014-05-22 16:41 |只看该作者
Linux 查cpu核数  
在Linux系统中,如何详细了解CPU的信息呢? 当然是通过cat /proc/cpuinfo来检查了,但是比如几个物理CPU/几核/几线程,这些问题怎么确定呢?
经过查看,我的开发机器是1个物理CPU,4核8线程,Intel(R) Core(TM) i7 CPU 860  @ 2.80GHz
记录一下,判断的过程和知识。

判断依据:
1.具有相同core id的cpu是同一个core的超线程。
2.具有相同physical id的cpu是同一颗cpu封装的线程或者cores。
英文版:
1.Physical id and core id are not necessarily consecutive but they are unique. Any cpu with the same core id are hyperthreads in the same core.
2.Any cpu with the same physical id are threads or cores in the same physical socket.

echo "logical CPU number:"
#逻辑CPU个数
cat /proc/cpuinfo | grep "processor" | wc -l

echo "physical CPU number:"
#物理CPU个数:
cat /proc/cpuinfo | grep "physical id" | sort -u | wc -l

echo "core number in a physical CPU:"
#每个物理CPU中Core的个数:
cat /proc/cpuinfo | grep "cpu cores" | uniq | awk -F: '{print $2}'
#查看core id的数量,即为所有物理CPU上的core的个数
cat /proc/cpuinfo | grep "core id" | uniq |  wc -l

#是否为超线程?
#如果有两个逻辑CPU具有相同的”core id”,那么超线程是打开的。或者siblings数目比cpu cores数目大。
#每个物理CPU中逻辑CPU(可能是core, threads或both)的个数:
cat /proc/cpuinfo | grep "siblings"


/proc/cpuinfo 文件包含系统上每个处理器的数据段落。/proc/cpuinfo 描述中有 6 个条目适用于多内核和超线程(HT)技术检查:processor, vendor id, physical id, siblings, core id 和 cpu cores。
processor 条目包括这一逻辑处理器的唯一标识符。
physical id 条目包括每个物理封装的唯一标识符。
core id 条目保存每个内核的唯一标识符。
siblings 条目列出了位于相同物理封装中的逻辑处理器的数量。
cpu cores 条目包含位于相同物理封装中的内核数量。
如果处理器为英特尔处理器,则 vendor id 条目中的字符串是 GenuineIntel。

1.拥有相同 physical id 的所有逻辑处理器共享同一个物理插座。每个 physical id 代表一个唯一的物理封装。
2.Siblings 表示位于这一物理封装上的逻辑处理器的数量。它们可能支持也可能不支持超线程(HT)技术。
3.每个 core id 均代表一个唯一的处理器内核。所有带有相同 core id 的逻辑处理器均位于同一个处理器内核上。
4.如果有一个以上逻辑处理器拥有相同的 core id 和 physical id,则说明系统支持超线程(HT)技术。
5.如果有两个或两个以上的逻辑处理器拥有相同的 physical id,但是 core id 不同,则说明这是一个多内核处理器。cpu cores 条目也可以表示是否支持多内核。

判断CPU是否64位,检查cpuinfo中的flags区段,看是否有lm标识。
Are the processors 64-bit?   
A 64-bit processor will have lm ("long mode" in the flags section of cpuinfo. A 32-bit processor will not.

Gitolite 构建 Git 服务器的权限管理  
参考资料:

    http://www.ossxp.com/doc/git/gitolite.html

架设环境debian squeeze,所有安装软件均为debian源上自带。

主要参考文献:

1、蒋鑫作品http://www.ossxp.com/doc/git/gitolite.html (堪称中文入门手册)

2、Gitolite自带文档https://github.com/sitaramc/gitolite/tree/master/doc (仔细阅读自带文档,会帮助解决细节问题)

3、Gitolite WIKI http://sitaramc.github.com/gitolite/   




Gitolite安装:

1、安装软件

sudo apt-get install gitolite git-core




2、产生G管理员的ssh key

确定某个账号,可以是server上的账号,也可以是某个客户端的账号,但是只能是唯一的。

在该账号下,用ssh-keygen产生ssh key。

在终端下运行ssh-keygen,默认在~/.ssh下产生文件 id_rsa.pub。

将这个文件放到服务器/tmp/下,命名为admin.pub。




2、建立git专用账号

sudo adduser --system --shell /bin/bash --group git

sudo adduser git ssh

sudo passwd git

以后上传下载工作都通过该账号进行,但是不直接使用该账号登陆,而是通过ssh key的认证。原理见文献1。




3、建立Gitolite仓库

su git进入git账号

gl-setup /tmp/admin.pub以admin.pub的账号为管理员,建立Gitolite仓库。

这时会在git账号下产生repositories目录,下面有两个子目录gitolite-admin.git和testing.git




4、初涉Gitolite管理

在G管理员账号下,运行 git clone git@server_ip:gitolite_admin.git

这样在G管理员帐号下,就有一个gitolite_admin的文件夹,里面是管理gitolite仓库的配置文件和Key文件。


增加用户:

将某人的ssh key文件abc.pub,复制到gitolite_admin/Keydir下;

然后 git add Keydir/abc.pub

git commit -m 'add abc'

git push origin master

这样就添加好了abc用户。

Gitolite是管理git用户的,但Gitolite本身又是通过git来操作的。很有意思吧!

相信删除的方法不用我讲了吧!




配置用户权限:

Gitolite是用来管理用户行为的,这个有conf/gitolite.conf完成。

下面所有例子来自参考文献1。由于个别地方已不适用,所以稍作修改。

下面我们看一个简单的授权文件:


1   @admin = jiangxin wangsheng 23   repo gitolite-admin4       RW+                 = jiangxin56   repo ossxp/..*7       C                   = @admin8       RW                  = @all910  repo testing11      RW+                         =   @admin12      RW      master              =   junio13      RW+     pu                  =   junio14      RW      cogito$             =   pasky15      RW      bw/                 =   linus16      -                           =   somebody17      RW      tmp/                =   @all18      RW      refs/tags/v[0-9]    =   junio在上面的示例中,我们演示了很多授权指令。

•第1行,定义了用户组 @admin,包含两个用户 jiangxin 和 wangsheng。

•第3-4行,定义了版本库 gitolite-admin。并指定只有用户 jiangxin 才能够访问,并拥有读(R)写(W)和强制更新(+)的权限。

•第6行,通过正则表达式定义了一组版本库,即在 ossxp/ 目录下的所有版本库。

•第7行,用户组 @admin 中的用户,可以在 ossxp/ 目录下创建版本库。

创建版本库的用户,具有对版本库操作的所有权限。

•第8行,所有用户都可以读写 ossxp 目录下的版本库,但不能强制更新。

(注意:RW和C分开两行是指软件仓库的权限,RWC在一行是分支的权限。见gitolite文档wildcard-repositories.mkd)

•第9行开始,定义的 testing 版本库授权使用了引用授权语法。

•第11行,用户组 @admin 对所有的分支和里程碑拥有读写、重置、添加和删除的授权。

•第12行,用户 junio 可以读写 master 分支。(还包括名字以 master 开头的其他分支,如果有的话)。

•第13行,用户 junio 可以读写、强制更新、创建以及删除 pu 开头的分支。

•第14行,用户 pasky 可以读写 cogito 分支。 (仅此分支,精确匹配)。




5、添加版本库

a、建一个空版本库

只需要在conf/gitolite.conf中添加一个规则,比如

repo work1

RW+=@all

这样gitolite就会自动创建一个空的版本库。

b、上传已有版本库

如上面的例子第6~8行中设定的规则,可以由admin(或指定其他账号),在指定目录下上传版本库。

在本机的版本库下执行:

git remote add r-server git@server_ipssxp/repo.git

git push r-server master

即推送完成。




6、高级管理


在4里,提到了大部分权限管理的情况。如果还不够用,就要进入通配符授权:

a、用户私有版本库

授权文件如下:

1  @administrators = jiangxin admin23  repo users/CREATOR/.+$4      C = @all5      R = @administrators说明:用户可以在自己的名字空间( /users/<userid>/ )下,自己创建版本库。

CREATOR是所有用户的通配符。创建者对版本库有最高权限,其他人只有读权限(当然可以另外设置)。

b、用户私有分支


授权文件:

repo test/repo4    RW+   dev/USER/          = @all    RW+   master         = @dev说明:

•所有用户都可以在 refs/heads/dev/<userid>/ (自己的名字空间)下创建、删除分支。但是不能修改其他人的分支。
•用户组 @dev 中的用户,对 master 分支具有读写和强制更新的权限,但是不能删除。
更改好配置文件后,同样适用git的方法,push到server上去。



7、Gitweb

上述操作的结果都没有直观的显示,这对将来的用户会造成一定的了解障碍。

这个障碍可以通过Gitweb来克服。Gitweb是一个网页前端,它的工作就是将git仓库的内容用网页形式展现出来。(如git.kernel.org上密密麻麻的仓库与分支)

这样开发者会更清楚地知道,去找自己需要的东西。

1、安装软件

sudo apt-get install gitweb

2、修改/etc/gitweb.conf

$projectroot = "/data/git-repo" <-- 此处应该是gitolite仓库的位置。我将之前git账号下的repositories移出来了,然后做了个链接回去(ln -s /data/git-repo /home/git/repositories)。

3、配置web

修改/etc/apache2/sites-available/default

我将原来的/var/www的内容换成了:

DocumentRoot /var/www                                                         
    <Directory /var/www>                                                           
        Options ExecCGI Indexes +FollowSymLinks MultiViews                        
        Order allow,deny                                                           
        Allow from all                                                            
        AllowOverride all                                                         
        AddHandler cgi-script cgi                                                  
        DirectoryIndex gitweb.cgi                                                  
        SetEnv  GITWEB_CONFIG  /etc/gitweb.conf                                    
    </Directory>     


然后,在/var/www下执行

sudo ln -s /usr/share/gitweb/* .

sudo ln -s gitweb.cgi index.html

这样进入http://server-ip就可以看到类似git.kernel.org的东东了。

对了,别忘了修改仓库的权限(chmod a+x /data/git-repo -R)

4、将www-data加入git组

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
9 [报告]
发表于 2014-05-22 16:42 |只看该作者
Linux操作系统下三种配置环境变量的方法  
在linux下做开发首先就是需要配置环境变量,下面以配置java环境变量为例介绍三种配置环境变量的方法。


1.修改/etc/profile文件

如果你的计算机仅仅作为开发使用时推荐使用这种方法,因为所有用户的shell都有权使用这些环境变量,可能会给系统带来安全性问题。



(1)用文本编辑器打开/etc/profile



(2)在profile文件末尾加入:

JAVA_HOME=/usr/share/jdk1.5.0_05

PATH=$JAVA_HOME/binPATH

CLASSPATH=.JAVA_HOME/lib/dt.jarJAVA_HOME/lib/tools.jar

export JAVA_HOME

export PATH

export CLASSPATH



(3)重新登录



注解:

a. 你要将 /usr/share/jdk1.5.0_05jdk 改为你的jdk安装目录



b. linux下用冒号“:”来分隔路径



c. $PATH / $CLASSPATH / $JAVA_HOME 是用来引用原来的环境变量的值,在设置环境变量时特别要注意不能把原来的值给覆盖掉了,这是一种常见的错误。



d. CLASSPATH中当前目录“.”不能丢,把当前目录丢掉也是常见的错误。



e. export是把这三个变量导出为全局变量。



f. 大小写必须严格区分。



2. 修改.bashrc文件  

这种方法更为安全,它可以把使用这些环境变量的权限控制到用户级别,如果你需要给某个用户权限使用这些环境变量,你只需要修改其个人用户主目录下的.bashrc文件就可以了。



(1)用文本编辑器打开用户目录下的.bashrc文件



(2)在.bashrc文件末尾加入:  

set JAVA_HOME=/usr/share/jdk1.5.0_05

export JAVA_HOME

set PATH=$JAVA_HOME/binPATH

export PATH

set CLASSPATH=.JAVA_HOME/lib/dt.jarJAVA_HOME/lib/tools.jar

export CLASSPATH



(3)重新登录



3. 直接在shell下设置变量

不赞成使用这种方法,因为换个shell,你的设置就无效了,因此这种方法仅仅是临时使用,以后要使用的时候又要重新设置,比较麻烦。



只需在shell终端执行下列命令:

export JAVA_HOME=/usr/share/jdk1.5.0_05

export PATH=$JAVA_HOME/binPATH

export CLASSPATH=.JAVA_HOME/lib/dt.jarJAVA_HOME/lib/tools.jar
git 通过ssh 进行认证连接  
首先安装git

emerge -av git  一条命令搞定,如果你使用ubuntu redhat 有相应的yum  apt-get 工具,



git麻烦在用户管理及管理上,下面上三种解决办法:

# 如果需要团队里的每个人都对仓库有写权限,又不能给每个人在服务器上建立账户,那么提供 SSH 连接就是唯一的选择了。我们假设用来共享仓库的服务器已经安装了 SSH 服务,而且你通过它访问服务器。  
#   
# 有好几个办法可以让团队的每个人都有访问权。

第一个办法 是给每个人建立一个账户,直截了当但过于繁琐。反复的运行 adduser 并且给所有人设定临时密码可不是好玩的。  
#   
# 第二个办法 是在主机上建立一个 git 账户,让每个需要写权限的人发送一个 SSH 公钥,然后将其加入 git 账户的 ~/.ssh /authorized_keys 文件。这样一来,所有人都将通过 git 账户访问主机。这丝毫不会影响提交的数据——访问主机用的身份不会影响 commit的记录。  
#   
# 另一个办法 是让 SSH 服务器通过某个 LDAP 服务,或者其他已经设定好的集中授权机制,来进行授权。只要每个人都能获得主机的 shell 访问权,任何可用的 SSH 授权机制都能达到相同效  # 如果需要团队里的每个人都对仓库有写权限,又不能给每个人在服务器上建立账户,那么提供 SSH 连接就是唯一的选择了。我们假设用来共享仓库的服务器已经安装了 SSH 服务,而且你通过它访问服务器。  

#   

为了简便选用了第二种办法 ,这种办法采用SSH公钥认证。

这里为了演示建立user1 user2 两个用户分别模拟两个开发人员,
                 建立git 用户,源码是通过git 用户进行初始化,可以将 它当作项目经理
并各自修改密码


产生公钥

ssh-keygen -C "你的email地址"  -t rsa

后面直接回车直到结束,中间可以不需要任何设置,该命令将生成一对非对称的公/私密钥,默认它们被存储在:
XP/2003用户:c:/Documents and Settings/登陆名/.ssh
Vista用户: c:/Users/登陆名/.ssh

linux          :~/.ssh

下面分别为user1 user2 产生公钥,私钥






这样有/home/user1/.ssh 下会产生两个文件,id_rsa 私钥,和id_rsa.pub公钥文件

公钥样子大概如此





该.ssh文件夹下面,私钥放在id_rsa文件里面,不用理会它;

对于user2 ,git 用户作相同处理,然后各自的目录会生成相应的文件





然后需要将user1 user2 各自的公钥文件提供给git 用户,





2、在linux服务器上将公钥加到git用户的authorized_keys文件中。
  可以参考:http://github.com/git-on-windows/rookies
  git用户的建立及设置参考:http://progit.org/book/zh/ch4-4.html

只要把它们加入 authorized_keys 文件(译注:本例加入到了文件尾部):



这样认证就建好了

然后用git 用户在/home/git目录下建一个库 project_repos.git/



然后启运服务  /etc/init.d/git-daemon restart

当然也要启动sshd  

                 /etc/init.d/sshd start

user1 连接 (这里测试时将porject_repos.git 改为repos.git 了, 此系小节,可忽略)

.git包含的目录含义  
UPDATE: I’ve recieved some very helpful comments regarding corrections to the various files and what they do. Thanks for letting me know and keeping me on my toes.

One of the things I like best about Git is that it keeps all of its information in one place: your .git directory in your project’s root. If you haven’t been digging around it yet, don’t fret! There’s plenty of goodies to be had within it. Let’s take a look into the important files and folders and try to get a better sense of what’s going on under the hood.

The basic structure looks like this:

.|-- COMMIT_EDITMSG|-- FETCH_HEAD|-- HEAD|-- ORIG_HEAD|-- branches|-- config|-- description|-- hooks|    |-- applypatch-msg|    |-- commit-msg|    |-- post-commit|    |-- post-receive|    |-- post-update|    |-- pre-applypatch|    |-- pre-commit|    |-- pre-rebase|    |-- prepare-commit-msg|    `-- update|-- index|-- info|   `-- exclude|-- logs|   |-- HEAD|   `-- refs|-- objects`-- refs    |-- heads    |-- remotes    |-- stash    `-- tagsLet’s go over some of the normal files that you may see living in the base directory:

•COMMIT_EDITMSG: This is the last commit’s message. It’s not actually used by Git at all, but it’s there mostly for your reference after you made a commit.
•config: Contains settings for this repository. Specific configuration variables can be dumped in here (and even aliases!) What this file is most used for is defining where remotes live and some core settings, such as if your repository is bare or not.
•description: If you’re using gitweb or firing up git instaweb, this will show up when you view your repository or the list of all versioned repositories.
•FETCH_HEAD: The SHAs of branch/remote heads that were updated during the last git fetch
•HEAD: The current ref that you’re looking at. In most cases it’s probably refs/heads/master
•index: The staging area with meta-data such as timestamps, file names and also SHAs of the files that are already wrapped up by Git.
•packed-refs: Packs away dormant refs, this is not the definitive list of refs in your repository (the refs folder has the real ones!) Take a look at gitster’s comment to see more information on this.
•ORIG_HEAD: When doing a merge, this is the SHA of the branch you’re merging into.
•MERGE_HEAD: When doing a merge, this is the SHA of the branch you’re merging from.
•MERGE_MODE: Used to communicate constraints that were originally given to git merge to git commit when a merge conflicts, and a separate git commit is needed to conclude it. Currently --no-ff is the only constraints passed this way.
•MERGE_MSG: Enumerates conflicts that happen during your current merge.
•RENAMED-REF: Still trying to track this one down. From a basic grep through the source, it seems like this file is related to errors when saving refs.
There’s plenty of directories as well:

•hooks: A directory that will fast become your best friend: this contains scripts that are executed at certain times when working with Git, such as after a commit or before a rebase. An entire series of articles will be coming about hooks.
•info: Relatively uninteresting except for the exclude file that lives inside of it. We’ve seen this before in the ignoring files article, but as a reminder, you can use this file to ignore files for this project, but beware! It’s not versioned like a .gitignore file would be.
•logs: Contains history for different branches. Seems to be used mostly with the reflog command.
•objects: Git’s internal warehouse of blobs, all indexed by SHAs.
•rebase-apply: The workbench for rebasing and for git am. You can dig into its patch file when it does not apply cleanly if you’re brave.
•refs: The master copy of all refs that live in your repository, be they for stashes, tags, remote tracking branches, or local branches.
Just one word of wisdom when messing around with Git internals: make sure you know what you’re doing, and if not, have a backup! Messing around with the config files or hooks is pretty simple but I wouldn’t go spelunking in the datastore if I didn’t have to. If for some reason you are as part of your normal workflow, you might be doing it wrong.

There’s plenty more about the internals of Git that we haven’t covered yet. One of the best guides is the Git Community Book, and of course, you can just download the source for yourself and take a look. If you have more information about what’s going on in the .git folder, let us know in the comments!

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
10 [报告]
发表于 2014-05-22 16:44 |只看该作者
Git详解二: Git基础  
Git 基础
读完本章你就能上手使用 Git 了。本章将介绍几个最基本的,也是最常用的 Git 命令,以后绝大多数时间里用到的也就是这几个命令。读完本章,你就能初始化一个新的代码仓库,做一些适当配置;开始或停止跟踪某些文件;暂存或提交某些更 新。我们还会展示如何让 Git 忽略某些文件,或是名称符合特定模式的文件;如何既快且容易地撤消犯下的小错误;如何浏览项目的更新历史,查看某两次更新之间的差异;以及如何从远程仓库 拉数据下来或者推数据上去。





2.1  取得项目的 Git 仓库
有两种取得 Git 项目仓库的方法。第一种是在现存的目录下,通过导入所有文件来创建新的 Git 仓库。第二种是从已有的 Git 仓库克隆出一个新的镜像仓库来。

在工作目录中初始化新仓库
要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:

$ git init初始化后,在当前目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。不过目前,仅仅是按照既有的结构框架初始化好了里边所有的文件和目录,但我们还没有开始跟踪管理项目中的任何一个文件。(在第九章我们会详细说明刚才创建的.git 目录中究竟有哪些文件,以及都起些什么作用。)

如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:

$ git add *.c$ git add README$ git commit -m 'initial project version'稍后我们再逐一解释每条命令的意思。不过现在,你已经得到了一个实际维护着若干文件的 Git 仓库。

从现有仓库克隆
如果想对某个开源项目出一份力,可以先把该项目的 Git 仓库复制一份出来,这就需要用到 git clone 命令。如果你熟悉其他的 VCS 比如 Subversion,你可能已经注意到这里使用的是 clone 而不是 checkout。这是个非常重要的差别,Git 收取的是项目历史的所有数据(每一个文件的每一个版本),服务器上有的数据克隆之后本地也都有了。实际上,即便服务器的磁盘发生故障,用任何一个克隆出来 的客户端都可以重建服务器上的仓库,回到当初克隆时的状态(虽然可能会丢失某些服务器端的挂钩设置,但所有版本的数据仍旧还在,有关细节请参考第四章)。

克隆仓库的命令格式为 git clone 。比如,要克隆 Ruby 语言的 Git 代码仓库 Grit,可以用下面的命令:

$ git clone git://github.com/schacon/grit.git这会在当前目录下创建一个名为“grit”的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录,然后从中取出最新版本的文件拷贝。如果进入这个新建的grit 目录,你会看到项目中的所有文件已经在里边了,准备好后续的开发和使用。如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:

$ git clone git://github.com/schacon/grit.git mygrit唯一的差别就是,现在新建的目录成了 mygrit,其他的都和上边的一样。

Git 支持许多数据传输协议。之前的例子使用的是 git:// 协议,不过你也可以用 http(s):// 或者user@server:/path.git 表示的 SSH 传输协议。我们会在第四章详细介绍所有这些协议在服务器端该如何配置使用,以及各种方式之间的利弊。





2.2  记录每次更新到仓库
现在我们手上已经有了一个真实项目的 Git 仓库,并从这个仓库中取出了所有文件的工作拷贝。接下来,对这些文件作些修改,在完成了一个阶段的目标之后,提交本次更新到仓库。

请记住,工作目录下面的所有文件都不外乎这两种状态:已跟踪或未跟踪。已跟踪的文件是指本来就被纳入版本控制管理的文件,在上次快照中有它们的记 录,工作一段时间后,它们的状态可能是未更新,已修改或者已放入暂存区。而所有其他文件都属于未跟踪文件。它们既没有上次更新时的快照,也不在当前的暂存 区域。初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪文件,且状态为未修改。

在编辑过某些文件之后,Git 将这些文件标为已修改。我们逐步把这些修改过的文件放到暂存区域,直到最后一次性提交所有这些暂存起来的文件,如此重复。所以使用 Git 时的文件状态变化周期如图 2-1 所示。



图 2-1. 文件的状态变化周期
检查当前文件状态
要确定哪些文件当前处于什么状态,可以用 git status 命令。如果在克隆仓库之后立即执行此命令,会看到类似这样的输出:

$ git status# On branch masternothing to commit (working directory clean)这说明你现在的工作目录相当干净。换句话说,当前没有任何跟踪着的文件,也没有任何文件在上次提交后更改过。此外,上面的信息还表明,当前目录下没 有出现任何处于未跟踪的新文件,否则 Git 会在这里列出来。最后,该命令还显示了当前所在的分支是 master,这是默认的分支名称,实际是可以修改的,现在先不用考虑。下一章我们就会详细讨论分支和引用。

现在让我们用 vim 编辑一个新文件 README,保存退出后运行 git status 会看到该文件出现在未跟踪文件列表中:

$ vim README $ git status # On branch master # Untracked files: # (use "git add ..." to include in what will be committed) # # README nothing added to commit but untracked files present (use "git add" to track)就是在“Untracked files”这行下面。Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文件”,因而不用担心把临时文件什么的也归入版本管理。不过现在的例子中,我们确实想要跟踪管理 README 这个文件。

跟踪新文件
使用命令 git add 开始跟踪一个新文件。所以,要跟踪 README 文件,运行:

$ git add README此时再运行 git status 命令,会看到 README 文件已被跟踪,并处于暂存状态:

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README #只要在 “Changes to be committed” 这行下面的,就说明是已暂存状态。如果此时提交,那么该文件此时此刻的版本将被留存在历史记录中。你可能会想起之前我们使用git init 后就运行了 git add 命令,开始跟踪当前目录下的文件。在 git add 后面可以指明要跟踪的文件或目录路径。如果是目录的话,就说明要递归跟踪该目录下的所有文件。(译注:其实git add 的潜台词就是把目标文件快照放入暂存区域,也就是 add file into staged area,同时未曾跟踪过的文件标记为需要跟踪。这样就好理解后续 add 操作的实际意义了。)

暂存已修改文件
现在我们修改下之前已跟踪过的文件 benchmarks.rb,然后再次运行 status 命令,会看到这样的状态报告:

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # # Changed but not updated: # (use "git add ..." to update what will be committed) # # modified: benchmarks.rb #  文件 benchmarks.rb 出现在 “Changed but not updated” 这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。要暂存这次更新,需要运行git add 命令(这是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等)。现在让我们运行git add 将 benchmarks.rb 放到暂存区,然后再看看 git status 的输出:

$ git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb #现在两个文件都已暂存,下次提交时就会一并记录到仓库。假设此时,你想要在 benchmarks.rb 里再加条注释,重新编辑存盘后,准备好提交。不过且慢,再运行git status 看看:

$ vim benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb # # Changed but not updated: # (use "git add ..." to update what will be committed) # # modified: benchmarks.rb #  怎么回事?benchmarks.rb 文件出现了两次!一次算未暂存,一次算已暂存,这怎么可能呢?好吧,实际上 Git 只不过暂存了你运行 git add 命令时的版本,如果现在提交,那么提交的是添加注释前的版本,而非当前工作目录中的版本。所以,运行了git add 之后又作了修订的文件,需要重新运行 git add 把最新版本重新暂存起来:

$ git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb #忽略某些文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。来看一个实际的例子:

$ cat .gitignore*.[oa]*~第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的,我们用不着跟踪它们的版本。第二行告诉 Git 忽略所有以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。

文件 .gitignore 的格式规范如下:

•所有空行或者以注释符号 # 开头的行都会被 Git 忽略。
•可以使用标准的 glob 模式匹配。 * 匹配模式最后跟反斜杠(/)说明要忽略的是目录。 * 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如[0-9] 表示匹配所有 0 到 9 的数字)。

我们再看一个 .gitignore 文件的例子:

# 此为注释 – 将被 Git 忽略*.a       # 忽略所有 .a 结尾的文件!lib.a    # 但 lib.a 除外/TODO     # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODObuild/    # 忽略 build/ 目录下的所有文件doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt查看已暂存和未暂存的更新
实际上 git status 的显示比较简单,仅仅是列出了修改过的文件,如果要查看具体修改了什么地方,可以用 git diff 命令。稍后我们会详细介绍git diff,不过现在,它已经能回答我们的两个问题了:当前做的哪些更新还没有暂存?有哪些更新已经暂存起来准备好了下次提交? git diff 会使用文件补丁的格式显示具体添加和删除的行。

假如再次修改 README 文件后暂存,然后编辑 benchmarks.rb 文件后先别暂存,运行 status 命令,会看到:

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # # Changed but not updated: # (use "git add ..." to update what will be committed) # # modified: benchmarks.rb #  要查看尚未暂存的文件更新了哪些部分,不加参数直接输入 git diff:

$ git diffdiff --git a/benchmarks.rb b/benchmarks.rbindex 3cb747f..da65585 100644--- a/benchmarks.rb+++ b/benchmarks.rb@@ -36,6 +36,10 @@ def main  @commit.parents[0].parents[0].parents[0]  end  +  run_code(x, 'commits 1') do      +  git.commits.size    +  end      +         run_code(x, 'commits 2')do           log = git.commits('master', 15)           log.size此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。

若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cached 命令。(Git 1.6.1 及更高版本还允许使用git diff --staged,效果是相同的,但更好记些。)来看看实际的效果:

$ git diff --cacheddiff --git a/README b/READMEnew file mode 100644index 0000000..03902a1--- /dev/null+++ b/README2@@ -0,0 +1,5 @@+grit+ by Tom Preston-Werner, Chris Wanstrath+ [url]http://github.com/mojombo/grit++Grit
is a Ruby library for extracting information from a Git repository请注意,单单 git diff 不过是显示还没有暂存起来的改动,而不是这次工作和上次提交之间的差异。所以有时候你一下子暂存了所有更新过的文件后,运行git diff 后却什么也没有,就是这个原因。

像之前说的,暂存 benchmarks.rb 后再编辑,运行 git status 会看到暂存前后的两个版本:

$ git add benchmarks.rb$ echo '# test line' >> benchmarks.rb$ git status# On branch master## Changes to be committed:##        modified:   benchmarks.rb## Changed but not updated:##        modified:   benchmarks.rb#现在运行 git diff 看暂存前后的变化:

$ git diffdiff --git a/benchmarks.rb b/benchmarks.rbindex e445e28..86b2f7c 100644--- a/benchmarks.rb+++ b/benchmarks.rb@@ -127,3 +127,4 @@ end main()  ##pp Grit::GitRuby.cache_client.stats+# test line然后用 git diff --cached 查看已经暂存起来的变化:

$ git diff --cacheddiff --git a/benchmarks.rb b/benchmarks.rbindex 3cb747f..e445e28 100644--- a/benchmarks.rb+++ b/benchmarks.rb@@ -36,6 +36,10 @@ def main          @commit.parents[0].parents[0].parents[0]        end+        run_code(x, 'commits 1') do+          git.commits.size+        end+        run_code(x, 'commits 2') do          log = git.commits('master', 15)          log.size提交更新
现在的暂存区域已经准备妥当可以提交了。在此之前,请一定要确认还有什么修改过的或新建的文件还没有 git add 过,否则提交的时候不会记录这些还没暂存起来的变化。所以,每次准备提交前,先用git status 看下,是不是都已暂存起来了,然后再运行提交命令 git commit:

$ git commit这种方式会启动文本编辑器以便输入本次提交的说明。(默认会启用 shell 的环境变量 $EDITOR 所指定的软件,一般都是 vim 或 emacs。当然也可以按照第一章介绍的方式,使用git config --global core.editor 命令设定你喜欢的编辑软件。)

编辑器会显示类似下面的文本信息(本例选用 Vim 的屏显方式展示):

# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb ~ ~ ~ ".git/COMMIT_EDITMSG" 10L, 283C可以看到,默认的提交消息包含最后一次运行 git status 的输出,放在注释行里,另外开头还有一空行,供你输入提交说明。你完全可以去掉这些注释行,不过留着也没关系,多少能帮你回想起这次更新的内容有哪些。(如果觉得这还不够,可以用-v 选项将修改差异的每一行都包含到注释中来。)退出编辑器时,Git 会丢掉注释行,将说明内容和本次更新提交到仓库。

另外也可以用 -m 参数后跟提交说明的方式,在一行命令中提交更新:

$ git commit -m "Story 182: Fix benchmarks for speed"[master]: created 463dc4f: "Fix benchmarks for speed" 2 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 README好,现在你已经创建了第一个提交!可以看到,提交后它会告诉你,当前是在哪个分支(master)提交的,本次提交的完整 SHA-1 校验和是什么(463dc4f),以及在本次提交中,有多少文件修订过,多少行添改和删改过。

记住,提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入版本管理。每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。

跳过使用暂存区域
尽管使用暂存区域的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上-a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:

$ git status# On branch master## Changed but not updated:##        modified:   benchmarks.rb#$ git commit -a -m 'added new benchmarks'[master 83e38c7] added new benchmarks 1 files changed, 5 insertions(+), 0 deletions(-)看到了吗?提交之前不再需要 git add 文件 benchmarks.rb 了。

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

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changed but not updated” 部分(也就是_未暂存_清单)看到:

$ rm grit.gemspec $ git status # On branch master # # Changed but not updated: # (use "git add/rm ..." to update what will be committed) # # deleted: grit.gemspec #然后再运行 git rm 记录此次移除文件的操作:

$ git rm grit.gemspec rm 'grit.gemspec' $ git status # On branch master # # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # deleted: grit.gemspec #最后提交的时候,该文件就不再纳入版本管理了。如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母),以防误删除文件后丢失修改的内容。

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆.a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可:

$ git rm --cached readme.txt后面可以列出文件或者目录的名字,也可以使用 glob 模式。比方说:

$ git rm log/\*.log注意到星号 * 之前的反斜杠 \,因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开(译注:实际上不加反斜杠也可以运行,只不过按照 shell 扩展的话,仅仅删除指定目录下的文件而不会递归匹配。上面的例子本来就指定了目录,所以效果等同,但下面的例子就会用递归方式匹配,所以必须加反斜 杠。)。此命令删除所有log/ 目录下扩展名为 .log 的文件。类似的比如:

$ git rm \*~会递归删除当前目录及其子目录中所有 ~ 结尾的文件。

移动文件
不像其他的 VCS 系统,Git 并不跟踪文件移动操作。如果在 Git 中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。不过 Git 非常聪明,它会推断出究竟发生了什么,至于具体是如何做到的,我们稍后再谈。

既然如此,当你看到 Git 的 mv 命令时一定会困惑不已。要在 Git 中对文件改名,可以这么做:

$ git mv file_from file_to它会恰如预期般正常工作。实际上,即便此时查看状态信息,也会明白无误地看到关于重命名操作的说明:

$ git mv README.txt README $ git status # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # renamed: README.txt -> README #其实,运行 git mv 就相当于运行了下面三条命令:

$ mv README.txt README$ git rm README.txt$ git add README如此分开操作,Git 也会意识到这是一次改名,所以不管何种方式都一样。当然,直接用 git mv 轻便得多,不过有时候用其他工具批处理改名的话,要记得在提交前删除老的文件名,再添加新的文件名。



2.3  查看提交历史
在提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,可以使用 git log 命令查看。

接下来的例子会用我专门用于演示的 simplegit 项目,运行下面的命令获取该项目源代码:

git clone git://github.com/schacon/simplegit-progit.git然后在此项目中运行 git log,应该会看到下面的输出:

$ git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 first commit   默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面。看到了吗,每次更新都有一个 SHA-1 校验和、作者的名字和电子邮件地址、提交时间,最后缩进一个段落显示提交说明。

git log 有许多选项可以帮助你搜寻感兴趣的提交,接下来我们介绍些最常用的。

我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新:

$ git log -p -2 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -18,8 +18,3 @@ class SimpleGit end end - -if $0 == __FILE__ - git = SimpleGit.new - puts git.show -end \ No newline at end of file  在做代码审查,或者要快速浏览其他协作者提交的更新都作了哪些改动时,就可以用这个选项。此外,还有许多摘要选项可以用,比如 --stat,仅显示简要的增改行数统计:

$ git log --stat commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number Rakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code lib/simplegit.rb | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-) commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon Date: Sat Mar 15 10:31:28 2008 -0700 first commit README | 6 ++++++ Rakefile | 23 +++++++++++++++++++++++ lib/simplegit.rb | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 0 deletions(-)   每个提交都列出了修改过的文件,以及其中添加和移除的行数,并在最后列出所有增减行数小计。还有个常用的 --pretty 选项,可以指定使用完全不同于默认格式的方式展示提交历史。比如用oneline 将每个提交放在一行显示,这在提交数很大时非常有用。另外还有 short,full 和fuller 可以用,展示的信息或多或少有些不同,请自己动手实践一下看看效果如何。

$ git log --pretty=onelineca82a6dff817ec66f44342007202690a93763949 changed the version number085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test codea11bef06a3f659402fe7563abf99ad00de2209e6 first commit但最有意思的是 format,可以定制要显示的记录格式,这样的输出便于后期编程提取分析,像这样:

$ git log --pretty=format:"%h - %an, %ar : %s"ca82a6d - Scott Chacon, 11 months ago : changed the version number085bb3b - Scott Chacon, 11 months ago : removed unnecessary test codea11bef0 - Scott Chacon, 11 months ago : first commit表 2-1 列出了常用的格式占位符写法及其代表的意义。

选项         说明%H        提交对象(commit)的完整哈希字串%h        提交对象的简短哈希字串%T        树对象(tree)的完整哈希字串%t        树对象的简短哈希字串%P        父对象(parent)的完整哈希字串%p        父对象的简短哈希字串%an        作者(author)的名字%ae        作者的电子邮件地址%ad        作者修订日期(可以用 -date= 选项定制格式)%ar        作者修订日期,按多久以前的方式显示%cn        提交者(committer)的名字%ce        提交者的电子邮件地址%cd        提交日期%cr        提交日期,按多久以前的方式显示%s        提交说明你一定奇怪_作者(author)_和_提交者(committer)_之间究竟有何差别,其实作者指的是实际作出修改的人,提交者指的是最后将此 工作成果提交到仓库的人。所以,当你为某个项目发布补丁,然后某个核心成员将你的补丁并入项目时,你就是作者,而那个核心成员就是提交者。我们会在第五章 再详细介绍两者之间的细微差别。

用 oneline 或 format 时结合 --graph 选项,可以看到开头多出一些 ASCII 字符串表示的简单图形,形象地展示了每个提交所在的分支及其分化衍合情况。在我们之前提到的 Grit 项目仓库中可以看到:

$ git log --pretty=format:"%h %s" --graph* 2d3acf9 ignore errors from SIGCHLD on trap*  5e3ee11 Merge branch 'master' of git://github.com/dustin/grit|\| * 420eac9 Added a method for getting the current branch.* | 30e367c timeout code and tests* | 5a09431 add timeout protection to grit* | e1193f8 support for heads with slashes in them|/* d6016bc require time for xmlschema*  11d191e Merge branch 'defunkt' into local以上只是简单介绍了一些 git log 命令支持的选项。表 2-2 还列出了一些其他常用的选项及其释义。

选项 说明-p 按补丁格式显示每个更新之间的差异。--stat 显示每次更新的文件修改统计信息。--shortstat 只显示 --stat 中最后的行数修改添加移除统计。--name-only 仅在提交信息后显示已修改的文件清单。--name-status 显示新增、修改、删除的文件清单。--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。--graph 显示 ASCII 图形表示的分支合并历史。--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。限制输出长度
除了定制输出格式的选项之外,git log 还有许多非常实用的限制输出长度的选项,也就是只输出部分提交信息。之前我们已经看到过 -2 了,它只显示最近的两条提交,实际上,这是 - 选项的写法,其中的 n 可以是任何自然数,表示仅显示最近的若干条提交。不过实践中我们是不太用这个选项的,Git 在输出所有提交时会自动调用分页程序(less),要看更早的更新只需翻到下页即可。

另外还有按照时间作限制的选项,比如 --since 和 --until。下面的命令列出所有最近两周内的提交:

$ git log --since=2.weeks你可以给出各种时间格式,比如说具体的某一天(“2008-01-15”),或者是多久以前(“2 years 1 day 3 minutes ago”)。

还可以给出若干搜索条件,列出符合的提交。用 --author 选项显示指定作者的提交,用 --grep 选项搜索提交说明中的关键字。(请注意,如果要得到同时满足这两个选项搜索条件的提交,就必须用--all-match 选项。)

如果只关心某些文件或者目录的历史提交,可以在 git log 选项的最后指定它们的路径。因为是放在最后位置上的选项,所以用两个短划线(--)隔开之前的选项和后面限定的路径名。

表 2-3 还列出了其他常用的类似选项。

选项 说明-(n)        仅显示最近的 n 条提交--since, --after 仅显示指定时间之后的提交。--until, --before 仅显示指定时间之前的提交。--author 仅显示指定作者相关的提交。--committer 仅显示指定提交者相关的提交。来看一个实际的例子,如果要查看 Git 仓库中,2008 年 10 月期间,Junio Hamano 提交的但未合并的测试脚本(位于项目的 t/ 目录下的文件),可以用下面的查询命令:

$ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \   --before="2008-11-01" --no-merges -- t/5610e3b - Fix testcase failure when extended attributeacd3b9e - Enhance hold_lock_file_for_{update,append}()f563754 - demonstrate breakage of detached checkout wid1a43f2 - reset --hard/read-tree --reset -u: remove un51a94af - Fix "checkout --track -b newbranch" on detacb0ad11e - pull: allow "git pull origin $somethingcurGit 项目有 20,000 多条提交,但我们给出搜索选项后,仅列出了其中满足条件的 6 条。

使用图形化工具查阅提交历史
有时候图形化工具更容易展示历史提交的变化,随 Git 一同发布的 gitk 就是这样一种工具。它是用 Tcl/Tk 写成的,基本上相当于 git log 命令的可视化版本,凡是git log 可以用的选项也都能用在 gitk 上。在项目工作目录中输入 gitk 命令后,就会启动图 2-2 所示的界面。



图 2-2. gitk 的图形界面
上半个窗口显示的是历次提交的分支祖先图谱,下半个窗口显示当前点选的提交对应的具体差异。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP