git笔记
1 git简介
git是一个分布式版本管理系统。版本管理系统用于记录文件的变化历史。git和其他版本管理工具的区别主要有两点。首先git不会记录文件变更了什么(比如:删除第2行),而是记录文件变更后的快照。其次git是分布式的。git会下载文件的全部历史到本地,因此无需联网也可以正常工作。
2 获取帮助
使用命令 git help
、 git <verb> --help
或 git help <verb>
可以获得git命令帮助信息。如果忘记了git命令选项,可以通过这些命令获得帮助。
3 开始工作
3.1 初始化仓库
git提供了两种方法初始化数据库。 git init <directory>
将空目录<directory>初始化为git仓库。 git clone <URL>
通过复制另一个git仓库的方式,完成仓库初始化。在初始化过程中,git会在仓库所在目录下建立子目录 .git
,保存仓库信息。 .git
子目录默认是隐藏的。
3.2 文件状态
git仓库同时也是一个目录,并非目录下的每个文件都被纳入git仓库。没有被纳入仓库的文件叫做未跟踪(untracked)的。纳入仓库后,一个文件可以具有三种状态:已提交(committed)表示文件快照已经写入数据库。已暂存(staged)表示对发生变更的文件做了标记,将在下次提交时写入数据库。已修改表示文件已经发生了变更,但是尚未提交或暂存。使用命令 git status
可以查看当前的仓库状态:是否有文件未跟踪,或者是否有文件变更。 git status -s
可以提供文件状态的简略的输出。
3.3 新建、移动、删除
如果要向仓库增加一个新文件,可以在目录下建立并编辑文件,然后使用 git add
跟踪文件。命令 git add
同样可以暂存一个已变更的文件。Listing 1: git add后,文件变为已暂存状态
git add new_file git add modified_file
如果要移动(重命名)文件,可以使用命令 git mv <old_name> <new_name>
。如果要删除一个文件,可以使用 git rm <filename>
。如果只希望从仓库中删除文件,但在目录下仍然保留着文件可以使用 git rm --cached <filename>
。
3.4 忽略某些文件
如果一些文件在本地工作时是必须的,但是这些文件不应当保存到git仓库中,可以将文件名(支持通配符)添加到.gitignore文件中。如果文件已经保存到暂存区或已经提交,可以先用 git rm --cached <filename>
将文件从git仓库中移除,然后将文件名添加到.gitignore中。Listing 2: .gitignore
# 忽略*.a文件 *.a # 但不忽略lib.a !lib.a # 忽略build/目录下的所有文件 build/
3.5 对比差异
前面提到文件在目录中可能处于下列四种状态之一:未跟踪、已修改、已暂存、已提交。我们将未跟踪和已修改的文件(集合)叫做工作区,将已暂存的文件叫做暂存区。使用 git diff
可以对比工作区和暂存区的差异。使用 git diff --staged
可以对比暂存区和已提交文件的差异。
3.6 取消暂存或修改
如果要取消对一个文件的暂存,可以使用 git reset HEAD <filename>
。如果要撤销对一个文件的修改,可以使用 git checkout -- <filename>
将文件恢复到上一次提交的状态。
3.7 提交
在完成文件编辑之后,使用 git commit
可以将暂存的变更提交到数据库。在提交时git会调用默认的编辑器,要求输入变更消息。使用 git commit -m <消息>
可以直接设定变更消息。使用 git commit -a
可以自动将未跟踪文件添加到暂存区,然后提交。
3.8 查看工作记录
使用 git log
可以查看提交记录。 git log
支持很多选项。 -p
表示显示两次提交的差异。 -2
表示显示最近2次提交记录。 --stat
表示显示提交的统计信息。 --since=2.weeks
表示显示近两周的提交。 --since="2008-01-15"
表示显示从2008年1月15日以来的提交。 --since
有一个别名 --after
。类似的还有 --until
和 --before
。 --author=john
表示显示john的提交。 --pretty-format="%h -%an %ar %s"
表示按照自定义格式显示提交记录。常用的格式符号有
%H | 提交的哈希 |
%h | 提交的短哈希 |
%T | 树对象哈希 |
%t | 树对象短哈希 |
%P | 父对象哈希 |
%p | 父对象短哈希 |
%an | 作者名字 |
%ae | 作者电子邮箱 |
%ad | 修订日期 |
%ar | 修订日期距今时间 |
%cn | 提交者名字 |
%ce | 提交者电子邮箱 |
%cd | 提交日期 |
%cr | 提交日期距今时间 |
%s | 提交说明 |
4 与他人协作
为了与他人协作,你需要将本地仓库和远程仓库关联起来。在使用 git clone
初始化仓库时,本地仓库和远程仓库自动建立了关联。对于使用 git init
初始化的本地仓库,需要使用 git remote add <name> <url>
添加远程仓库。本地仓库可以添加多个远程仓库。使用 git remote -v
可以查看已经添加的远程仓库。建立关联之后,就可以拉取或推送代码。使用 git fetch <remote>
可以将远程仓库的变更拉取到本地。使用 git push <remote> <branch>
则将本地变更推送到远程仓库。如果不再需要使用远程仓库,可以使用 git rm <remote>
将远程仓库在本地的数据删除,并取消和远程仓库的关联。
使用 git remote -v
可以查看全部的远程仓库。使用 git remote show <remote>
可以查看远程仓库信息。
5 里程碑
git提供标签功能来管理工作里程碑。使用命令 git tag <tag>
可以创建标签。使用 git tag <tag> -a -m <message>
可以在创建标签的时候添加附注。使用命令 git tag
可以列出所有标签。如果标签数量太多,可以使用 git tag -l "1.0.*"
列出部分标签。使用 git show <tag>
可以查看标签的信息。使用 git push <remote> <tag>
可以将特定分支推送到远程仓库。使用 git push <remote> --tags
可以将全部本地标签推送到远程仓库。
6 使用分支
git允许仓库中包含多个分支。第1个分支叫主(master)分支。git仓库初始化完成后,就切换到主分支。如果一些工作需要的时间较长,将未完成的工作合并到主分支上又容易影响其他人的工作。这时可以使用分支来管理工作。使用 git branch <branch>
可以创建分支。创建分支之后,使用命令 git checkout <branch>
可以将工作目录切换到对应分支上。这两步操作也可以使用一条命令完成: git checkout -b <branch>
。在分支上的提交操作和在主分支上一样。当分支上的任务完成后,再次切换回主分支,然后使用命令 git merge <branch>
就可以将对应分支的工作合并到主分支上。其他分支之间的合并也是类似的。当不再需要一个分支时,可以使用 git branch -d <branch>
删除它。使用 git branch [-v]
可以查看全部的分支。使用 git branch --merged
可以查看已经合并过的分支。使用 git push <remote> <branch>
可以向远程仓库推送本地分支。
7 配置
git提供了命令 git config
来查看和编辑配置。这些配置保存在配置文件中。git配置文件保存在3个地方:
- /etc/gitconfig。系统配置,对全部用户生效。通过命令
git config --system
编辑。 /.gitconfig。用户配置。对当前用户生效。通过命令 ~git config --global
编辑。- 项目目录/.git/config。项目配置。对当前项目生效。通过在项目目录下执行命令
git config
配置。
使用命令 git config --list --show-origin
可以查看所有的配置项和记录这些它们的配置文件。如果要查看某个特定的配置项,可以使用 git config 配置项
。常用的配置项有:
- user.name。用户名。
- user.email。用户电子邮箱。
- core.editor。提交信息编辑器。
- core.autocrlf。是否在提交时将CRLF转换为LF,并在签出时将LF转换为CRLF。
- core.quotepath。是否对文件路径进行转义。
8 git内部原理
git仓库信息保存在.git子目录中。.git子目录包含下列文件和目录:
HEAD | 当前分支指针 |
branches/ | 新版本不再使用 |
config | 配置信息 |
description | 供GitWeb使用 |
hooks/ | 钩子 |
index | 暂存区信息 |
info/ | |
objects/ | 数据内容 |
refs/ | 指针 |
git将文件快照保存在objects目录下,快照文件名是文件内容的哈希值。哈希值前两个字母相同的快照放到objects目录的同一个子目录下,子目录就以这两个字母命名。git采用SHA-1算法计算哈希。目录的快照是一个tree对象,包含了目录中文件的名字和文件快照的哈希。每次提交,git会创建一个commit对象,包含提交目录tree对象的哈希、作者和提交消息。git保存一个特殊的HEAD指针,指向当前分支的tree对象。
9 常见问题
9.1 如何忽略已提交文件的变更
git update-index --assume-unchanged <file> git update-index --no-assume-unchanged <file> # 撤销 git ls-files -v|grep '^h' # 查看哪些assume-unchanged
9.2 如何保存临时修改
使用git stash可以保存临时修改。
git stash git stash list git stash apply
9.3 如何处理中文文件名乱码
git config --global core.quotepath false
9.4 如何git日志出现乱码。
git config --global i18n.logoutputencoding gbk
9.5 fatal: refusing to merge unrelated histories
执行git pull时报告
fatal: refusing to merge unrelated histories
原因是两个仓库中的修改历史不同。解决方法是加入–allow-unrelated-histories参数。
10 参考资料
- https://my.oschina.net/qiangdada/blog/800093
- https://my.oschina.net/qiangdada/blog/808527
- https://stackoverflow.com/questions/7527982/applying-gitignore-to-committed-files
- https://git-scm.com/book/zh/v2
- http://git.oschina.net/progit/
11 修改记录
- 2017年1月17日 增加查看日志和保存临时修改部分。
- 2017年06月16日 将文件改为rst格式。
- 2017年09月05日 增加忽略已提交文件变更的方法。
- 2017年09月06日 增加常见问题部分。
- 2021年07月04日 调整结构和文字。