Git学习
Git 只关心文件数据的整体是否发生变化
Git 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。该字串由 40 个十六进制字符(0-9 及 a-f)组成,看起 来就像是: 24b9da6552252987aa493b52f8696cd6d3b00373 所有保 存在 Git 数据库中的东西都是用此哈希值来作索引的
基本的 Git 工作流程如下所示:
1. 在工作目录中修改某些文件。
2. 对这些修改了的文件作快照,并保存到暂存区域。
3. 提交更新,将保存在暂存区域的文件快照转储到 git 目录中。
我们可以从文件所处的位置来判断状态:如果是 git 目录中保存着的特定版本文 件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。
环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在 以下三个不同的地方:
• /etc/gitconfig文件:系统中对所有用户都普遍适用的配置。若使用 git config 时 用 --system 选项,读写的就是这个文件。
• ~/.gitconfig文件:用户目录下的配置文件只适用于该用户。若使用 git config 时 用 --global 选项,读写的就是这个文件。
• 当前项目的 git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这 里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。
要检查已有的配置信息,可以使用 git config --list 命令
查阅某个环境变量的设定,只要把特定的名字跟在后面即可 Eg:$ git config user.name
获取帮助
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行: git init 初始化后,在当前目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都 存放在这个目录中。
克隆仓库的命令格式为
git clone [url] eg:git clone git://github.com/schacon/grit.git
(检查当前文件状态)
要确定哪些文件当前处于什么状态,可以用 git status 命令。
对于任何一个文件,在 Git 内都只有三 种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该 文件已经被安全地保存在本地数据库中了;已修改表示修改了某个文件,但还没有提交保 存;已暂存表示把已修改的文件放在下次提交时要保存的清单中。
vim 编辑一个新文件 README,保存退出后运行 git status 会看到该文件 出现在未跟踪文件列表中:
在“Untracked files”这行下面。Git 不会自动将之纳入跟踪范围,除非你明明白 白地告诉它这么做,因而不用担心把临时文件什么的也归入版本管理。
(跟踪新文件)使用命令 git add 开始跟踪一个新文件。所以,要跟踪 README 文件,运行:
只要在 “Changes to be committed” 这行下面的,就说明是已暂存状态。如果此时提 交,那么该文件此时此刻的版本将被留存在历史记录中。
(暂存已修改文件)
修改下之前已跟踪过的文件 benchmarks.rb,然后再次运行 status 命令
文件 benchmarks.rb 出现在 “Changed but not updated” 这行下面,说明已跟踪文件 的内容发生了变化,但还没有放到暂存区。
现在让我们运行 git add 将 benchmarks.rb 放到暂存区,假设此时,你想要在 bench- marks.rb 里再加条注释,重新编辑存盘后,准备好提交。不过且慢,再运行 git status 看看:
bench.c 文件出现了两次!一次算未暂存,一次算已暂存,这怎么可能呢? 好吧,实际上 Git 只不过暂存了你运行 git add 命令时的版本,如果现在提交,那么提交 的是添加注释前的版本,而非当前工作目录中的版本。所以,运行了 git add 之后又作了 修订的文件,需要重新运行 git add 把最新版本重新暂存起来:
忽略某些文件
对于一些无需纳入或者系统中自动生成的文件,像是日志或者编辑过程中创建的,可以创建一个.gitignore的文件,列出要忽略的文件模式
$ cat .gitignore
*.[oa]
*~
# 此为注释 – 将被 Git 忽略
*.a # 忽略所有 .a 结尾的文件
!lib.a # 但 lib.a 除外
/TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO build/ # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是 编译过程中出现的,我们用不着跟踪它们的版本。第二行告诉 Git 忽略所有以波浪符(~) 结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。此外,你可能 还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
文件 .gitignore 的格式规范如下:
• 所有空行或者以注释符号 # 开头的行都会被 Git 忽略。
• 可以使用标准的 glob 模式匹配。
• 匹配模式最后跟反斜杠(/)说明要忽略的是目录。
• 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
git diff 看暂存前后的变化:
提交更新
每次准备提交前,先用 git status 看下,是不是都已暂存起来了,然后再运行提交命 令 git commit
git commit
这种方式会启动文本编辑器以便输入本次提交的说明。(默认会启用 shell 的环境变量 $EDITOR 所指定的软件,一般都是 vim 或 emacs,编辑器会显示类似下面的文本信息
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# 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:
# new file: README
# new file: bench.c
也可以使用 -m 参数后跟提交说明的方式,在一行命令中提交更新:
提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,可以
在下次提交时纳入版本管理。每一次运行提交操作,都是对你项目作一次快照,以后可以回
到这个状态,或者进行比较。
移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区 域移除),然后提交。可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的 文件
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changed but not updated” 部分(也就是_未暂存_清单)看到:
然后再运行 git rm 记录此次移除文件的操作:
最后提交的时候,该文件就不再纳入版本管理了。如果删除之前修改过并且已经放到暂存 区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母),以防误删除文件后 丢失修改的内容。
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希 望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者 一堆 .a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可:
移动文件
Git 并不跟踪文件移动操作。如果在 Git 中重命名了某个文件, 仓库中存储的元数据并不会体现出这是一次改名操作要在 Git 中对文件改名,可以 这么做:
$ git mv file_from file_to //file_from原名 file_to新改的名
例子:
运行 git mv 就相当于运行了下面三条命令
$ mv README.txt README
$ git rm README.txt
$ git add README
查看提交历史
默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新:
在做代码审查,或者要快速浏览其他协作者提交的更新都作了哪些改动时,就可以用这个 选项。此外,还有许多摘要选项可以用,比如 --stat,仅显示简要的增改行数统计:
还有个常用的 --pretty 选项,可以指定使用完全不同于默认格式的方式展示提交历史比如用 oneline 将每个提交放在一行显示,这在提交数很大时非常有用。另外还有 short,full 和 fuller 可以用,展示的信息或多或少有些不同
--graph 选项可以看到开头多出一些 ASCII 字符串表 示的简单图形,形象地展示了每个提交所在的分支及其分化衍合情况
可以给出各种时间格式,比如说具体的某一天(“2008-01-15”),或者是多久以前 (“2 years 1 day 3 minutes ago”)。
还可以给出若干搜索条件,列出符合的提交。用 --author 选项显示指定作者的提交,用 --grep 选项搜索提交说明中的关键字。(请注意,如果要得到同时满足这两个选项搜索条 件的提交,就必须用 --all-match 选项。)
撤销操作
修改最后一次提交
有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才 的提交操作,可以使用 --amend 选项重新提交:
$ git commit --amend
此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命
令的话,相当于有机会重新编辑提交说明,而所提交的文件快照和之前的一样。
启动文本编辑器后,会看到上次提交时的说明,编辑它确认没问题后保存退出,就会使用
新的提交说明覆盖刚才失误的提交。
如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend 提交
$ git commit -m 'initial commit’
$ git add forgotten_file
$ git commit --amend
取消已经暂存的文件
有两个修改过的文件,我们想要分开提交,但不小心用 git add * 全加到了暂 存区域。该如何撤消暂存其中的一个文件呢
git add . :他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。
就在 “Changes to be committed” 下面,括号中有提示,可以使用 git reset HEAD <file>... 的方式取消暂存。好吧,我们来试试取消暂存 R 文件:
查看当前远程仓库:
git remote
git remote -v //显示对应的克隆地址,有多个远程仓库时此命令将全部列出
添加远程仓库
git remote add 仓库名 url(远程仓库存在的地址)
从远程仓库抓取数据
git fetch 远程仓库名 //从远程仓库中拉取本地仓库现在没有的数据
推送数据到远程仓库
git push [远程仓库名][分支名]
只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,并到自己的项目中,然后才可以再次推送。
查看远程仓库信息
git remote show [远程仓库名] //查看某个远程仓库的详细信息
远程仓库的删除和重命名
git remote rename //重命名
git remote rm 远程仓库名 //删除仓库
列显已有的标签
git tag
显示的标签按字母顺序排列,所以标签的先后并不表示重要程度的轻重。
新建标签
创建一个含附注类型的标签非常简单,用 -a 指定标签名字,-m指定了对应的标签说明:
git show 命令查看相应标签的版本信息,并连同显示打标签时的提交对象
轻量级标签
一个 -a,-s 或 -m 选项都不用,直接给出标签名字即可
验证标签
使用 git tag -v [tag-name]的方式验证已经签署的 标签。此命令会调用 GPG 来验证签名,所以你需要有签署者的公钥,存放在 keyring 中, 才能验证:
后期加注标签
只要在打标签的时候跟上对应提交对象的校验和(或前几位字符)即可:
git tag -a v1.2 (对应提交对象的校验和或前几位字符) //给对应要添加的项目打标签
git tag //查看已经存在的标签
git show v1.2 //查看标签的信息
分享标签
默认情况下,git push 并不会把标签传送到远端服务器上,只有通过显式命令才能分享
标签到远端仓库。其命令格式如同推送分支,运行 git push origin [tagname] 即可:
如果要一次推送所有(本地新增的)标签上去,可以使用 --tags 选项
Git 命令别名
如上输入git st和git status执行的结果是一样的
设置 last 命令
创建新分支:
切换分支
git checkout 要切换到的分支名 //加-b可以在创建分支的同时并且换到新创建的分支