本文是通过学习《Pro Git》–作者Scott Chacon 后所做的整理和思考笔记。
《Pro Git》中文版 PDF 下载见 http://www.linuxidc.com/Linux/2013-05/85066.htm
一.GIT管理下的文件周期
1.新添加的文件或文件夹是untracked状态,意思是git的版本管理里没有这个文件。
可以用git add来把这个文件加入git管理,之后就会是tracked中的stage状态了。
如果是新git clone或git init的文件,则是在tracked状态里的unmodified状态。
注1:新添了文件,untracked的状态:
注2:用git add <文件名> 将文件加入git管理后,文件是tracked下的staged状态
2.在git的管理下的状态是tracked状态,包括unmodified,modified和staged三种状态。
3.unmodified状态指本地的文件与版本库里该文件最近一次的提交是一致的。
4.一旦修改了文件,文件内容与版本库里该文件最近一次的提交内容不一致,状态便变成modified。此时可以用git add <文件> 来stage文件。
stage之后的文件可以用git commit <文件> 来提交文件或 git reset HEAD <文件> 来取消stage状态。
5.当一个文件已经stage后,如果再做修改,此时的状态是部分stage,部分modified。如果commit的话,会提交已经stage的那部分。
6.git add有多种功能,可以将untracked的文件track,可以将modified的文件stage,还可以将merge时conflict后来修改好的文件再次stage。
问题:为什么要有一个stage的状态?修改了文件要stage再commit不是很麻烦吗?
我的答案:commit是一次对所有stage过的文件的提交,没有针对某一个文件的commit。
一般说来,一次commit是完成一个版本的snapshot,可以修改一个文件就stage,也可以修改完了很多文件一起stage。stage就像一个箱子,把要commit的内容都装上去。然后对装箱的内容做commit操作。
如果修改好的文件可以直接提交,可以用git commit -a来自动stage,即对全部修改自动装箱提交。
二. 同一个文件的差异查看
用git status可以查看到文件的当前状态,如果要查看当前文件到底有多少内容没stage的或者stage的文件跟本地版本库最近一次提交的差异,可以用git diff来看
1. git diff
查看文件与stage的差异。比如已经stage了一个文件,然后又修改了它。用git diff可以查看到修改的内容部分。如果一个文件已经stage,之后并无修改,那么git diff的结果是没有任何差异。
2. git diff -cache(或者git version 1.6.1之后用git diff –staged )
查看stage文件与版本库最近一次提交的差异。
问题:如何查看版本库里不同版本之间的差异?
答案:用git log.比如可以用git log -p -2来查看最近两个版本之间的内容差异。详见下面四.查看版本。
三.删除和过滤文件
1.从版本库上删除文件,本地也不保留该文件
git rm <文件>,然后 git commit <文件>
这个操作会删除版本中该文件,且删除本地该文件。
如果只是删除本地文件,则git status会显示该文件的删除未stage。这不是我们想看到的,因为版本库依然在track该文件的状态。
附:如果文件修改了未commit的话,需要git rm -f来强制删除。
gir rm <文件> 中的文件可以用pattern来表示,比如\*.log, \*~ (\是转义字符)
问题1:如果本来想git rm,但是不小心rm了文件,应该怎么办呢?
我的答案:还未尝试,但是我觉得可以再执行git rm;如果有远程版本库的话,则先git pull,再git rm。
问题2:如果修改了文件名字,该怎样提交呢?
答案:git rm <老文件名>
再git add <新文件名>
再提交。
注: 对于文件重命名,可以直接用 git mv <旧文件名> <新文件名> 再commit即可。
问题3:本地误删了的文件,如何从本地版本库中找回?或者想回滚到之前的某个文件怎样做?
2.从版本库上删除文件,但本地保留
这是当不小心将不该track的文件提交了之后的处理办法。
git rm –cached <文件>
3.版本库上没有该文件,但本地保留
这种情况下版本会提示有文件untracked。如果我们不想让该文件untracked的状态老是被提示(我本来就不想它tracked,比如一些log文件,class文件,本地的配置文件等),可以让它们被ignore。
做法是: 在.gitignore文件里添加想要不被track的文件。
四.查看版本
版本管理工具最重要的功能不就是能提供不同版本给人查看和备份的作用吗?下面看如何查看版本。
命令:git log
不带参的时候,仅仅按时间倒序的顺序显示不同版本文件,内容包括SHA checksum,作者和comment。
最常用的参数:
-p:显示diff,具体内容的改变。
-<number>:显示最近几个版本。比如 -2 显示最近两个版本。
-stat:显示统计数据,哪些文件增减了多少行。
–pretty:显示格式为想要的样子,比如 –pretty=oneline是每个版本只显示一行,包括SHA和comment。
比如 –pretty=”%h – %an, %ar : %s”.以下是一些样式的选项:
git show <SHA-1>可以显示该commit的详细信息。<SHA-1>是commit的时候生成的checksum,可以输入完整的,也可以是前面一部分,一般说来8到10位就够了,即short SHA。
【使用范例】:
先用git log –abbrev-commit –pretty=oneline来显示所有的commit,每个commit显示为一行,用的是shot SHA-1.
再用git show <SHA>来查看你关心的那个commit。
–graph 和–pretty一起用,可以显示branch图形
查看log很适合用图形化工具,命令:gitk
五.回滚操作
如何放弃当前的修改是我之前一直想知道的,现在有答案了。
回滚包括将stage的文件回滚到unstaged的状态和将modified的文件回滚到修改之前的状态,即回滚到版本库中最近一次提交的内容。
从staged->unstaged: git reset HEAD <文件>
从modified->unmodified:git checkout –<文件>(这个命令是git 1.6.1和之后的版本才有的,但是注意风险,因为一旦做了这个操作,修改后的内容就找不回来了)
问题:如何回滚版本库里的文件?
网上参考答案:
——————————————BEGIN—————————————————
git reset是指将当前head的内容重置,不会留log信息。
git reset HEAD filename 从暂存区中移除文件
git reset –hard HEAD~3 会将最新的3次提交全部重置,就像没有提交过一样。
git reset –hard commit (38679ed709fd0a3767b79b93d0fba5bb8dd235f8) 回退到 38679ed709fd0a3767b79b93d0fba5bb8dd235f8 版本
根据–soft –mixed –hard,会对working tree和index和HEAD进行重置:
git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息
git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可
git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容
——————————————–END—————————————————
六.远程版本库
从远程拷贝git clone URL
查看远程版本库的branch信息:进入克隆下来的目录,git remote,可显示远程的branch。
git remote -v可显示远程URL
当远程版本库有分支时,你可以选择添加某一个分支
git remote add <别名> <分支URL>
例如 git add pb git://github.com/paulbone/ticgit.git
现在再git remote -v就可以看到origin和pb两个branch了,其中origin是default的。
可以取出某个分支的最新代码:git fetch <分支>,可以看到pb/master便是取出的代码,它并没有合并到当前的工作目录里。如果要fetch并merge的话可以用git pull <分支>
六.分支的建立与rebase
创建分支:git branch <分支>
切换分支:git checkout <分支>
将另一个分支的内容合并到本分支:先切换到要被合并内容的分支,然后git merge <另一分支>
merge时当同一个文件同一部分产生了内容冲突时,需要手动修改冲突的文件然后再stage该文件。可以用git mergetool来图形化操作。
查看已经merge到本分支的所有分支:git branch –merged
可以删除已经merge过的分支:git branch -d <分支>
查看没有merge到本分支的所有分支:git branch –no-merged
删除没有merge过的分支:git branch -D <分支>, 即强制删除
七.远程分支