重学Git第一天


运行 Git 前的配置

查看所有的配置及它们所在的文件

1
git config --list --show-origin

用户信息

1
2
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

使用了–global 代表全局配置 如果想根据不同项目使用不同的用户名和邮件地址 可以在该项目目录下运行不带–global

检查配置信息

1
2
3
git config --list //查看所有配置
git config <key>//查看某一项配置 eg: git config user.name
git config --show-origin rerere.autoUpdate //查看原始配置

获取帮助

1
2
3
4
5
6
7
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
//以上三种命令都是等价的
//eg: 想要获取git config的命令手册 执行 git help config
//如果只需要可用选项的快速参考 可以使用-h来获取更简明的
eg: git add -h

Git 基础

获取 Git 仓库

获取 Git 仓库

  • 将未进行版本控制的本地目录转换为 Git 仓库
  • 从其它服务器 克隆 一个已存在的 Git 仓库。

1.从已存在的目录初始化仓库

1
2
3
4
1. cd project // cd /c/user/my_project
2. git init //初始化 将创建一个.git文件 包含Git仓库的所有文件 此时只是初始化 还未被追踪
3 git add // eg: git add *c 追踪指定的文件
4 git commit -m "..."//初始提交 这样我们就已经得到一个被追踪文件与初始提交的Git仓库

2.克隆现有的仓库

1
1. git clone "url" //git clone https://github.com/libgit2/libgit2 会在当前目录初始化.git 并将所有拉取的所有数据都存到.git文件夹 当你想自定义拉下来的仓库名 git clone url yourName

记录每次更新到仓库

每一个文件都是两种状态之一:已跟踪未跟踪

编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。 在工作时,你可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。

检查当前的状态

1
git status

跟踪新文件

1
2
git add fileName // eg: git add README.md
git status // 只要出现changes to be committed 就说明已经是暂存状态 如果此时提交 那么该文件在你运行git add时的版本将被留存在后续的历史记录中

git add 命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。

暂存已修改的文件

要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。

提交时提交的版本是最后一次 git add 的版本而不是运行 git commit 时的版本

状态简览

1
git status -s

忽略文件

一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。 来看一个实际的 .gitignore 例子:

1
2
3
$ cat .gitignore
*.[oa]
*~

gitignore的格式规范如下

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
  • 匹配模式可以以(/)开头防止递归。
  • 匹配模式可以以(/)结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(**)表示匹配任意中间目录,比如 a/**/z 可以匹配 a/za/b/za/b/c/z 等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 忽略所有的 .a 文件
*.a

# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a

# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO

# 忽略任何目录下名为 build 的文件夹
build/

# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt

# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf

查看已暂存和未暂存的修改

查看未暂存部分更新了哪些部分 不加参数直接输入 git diff

1
git diff

若要查看已暂存的将要添加到下次提交的内容 可以使用git diff --staged 将对比已暂存文件与最后一次提交的文件差异

1
git diff --staged

请注意,git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你一下子暂存了所有更新过的文件,运行 git diff 后却什么也没有,就是这个原因。

提交更新

git commit

1
$ git commit

可以在commit命令后面添加-m 将提交信息与命令行放在同一行

1
git commit -m "Story 182: Fix benchmarks for speed"

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

跳过使用暂存区域

只要在git commit加上-a选项 Git 就会自动把之前所有已经跟踪的文件暂存起来一并提交 从而跳过git add步骤:

1
git commit -a -m 'added new benchmarks'

需要小心使用 有时这个选项会将不需要的文件添加到提交中

移除文件

要从 Git 中移除某文件 需要先从已跟踪的文件清单(暂存区域)移除 然后提交 可以使用git rm 并连带从工作目录中删除指定的文件 以后不会出现在未跟踪的清单中

如果只是从工作目录中删除文件 运行git status时就会在“Changes not staged for commit” 部分(也就是 _未暂存清单_)看到:

1
2
3
4
5
6
7
8
9
10
11
$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

deleted: PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")

然后再运行git rm记录此次移除文件的操作

1
2
3
4
5
6
7
8
9
$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

deleted: PROJECTS.md

如果要删除之前修改过或已经放到暂存区的文件 则必须强制使用-f 用于防止误删尚未添加到快照的数据 这样的数据不能被 Git 恢复

如果想要将文件从 Git 仓库删除但是又想保留在当前工作目录中(文件留在磁盘但是不再追踪 Git)例如你忘记添加.gitignore文件 但是一不小心将日志文件或.a这样的编译文件添加到暂存区 这一方法很有用

使用--cached选项

1
git rm --cached README

git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。比如:

1
$ git rm log/\*.log

移动文件

要在 Git 中对文件改名

1
git mv file_from file_to

可以使用git status查看状态信息以及重命名操作的说明

git mv相当于以下的命令

1
2
3
$ mv README.md README
$ git rm README.md
$ git add README

查看提交历史

查看提交历史

git log

1
git log
  • -p-patch 显式每次提交所引入的差异(按补丁的形式输出) 也可以限制显式的日志条目数量

    1
    git log -p -2
  • --stat 查看每次提交的简略统计信息

1
git log --stat
  • --pretty使用不同的默认格式的方式展示提交信息
1
2
git log --pretty=oneline
git log --pretty=format:"%h - %an, %ar : %s";//定制记录的显式格式 对后期提取分析格外有用
  • git log --pretty=format 常用的选项
%H 提交的完整哈希值
%h 提交的简写哈希值
%T 树的完整哈希值
%t 树的简写哈希值
%P 父提交的完整哈希值
%p 父提交的简写哈希值
%an 作者名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 –date=选项 来定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期(距今多长时间)
%s 提交说明
  • git log 的常用选项
-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(用来定义自己的格式)。
--oneline --pretty=oneline --abbrev-commit 合用的简写。

限制输出长度

--since--until 这种按照时间作限制的选项很有用

1
$ git log --since=2.weeks //列出最近两周的所有提交

撤销操作

撤销操作

有时候我们漏提交了东西或者提交信息写错了 可以使用--amend选项来重新提交

1
git commit --amend

这个命令会将暂存区的文件提交 如果自从上次提交以来未做任何操修改(上次提交后立马执行次命令)那么快照会保存不变 所修改的只是提交信息

1
2
3
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

最终你只会有一个提交——第二次提交将代替第一次提交的结果。

从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。

修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。

取消暂存的操作

如果已经修改了两个文件并且想要将它们作为两次独立的修改提交 但是却意外地输入了 git add . 如果想取消暂存中的一个 使用 git reset HEAD … 来取消暂存

1
git reset HEAD <file>

撤销对文件的修改

使用 git checkout –

1
git checkout -- CONTRIBUTING.md

请务必记得 git checkout -- <file> 是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。

远程仓库的使用

远程仓库的使用

查看已经配置好的远程仓库服务器 git remote

1
2
git clone https://github.com/schacon/ticgit
git remote

如果指定-v 会显示需要读写远程仓库使用的 Git 保存的简写与之对应的 URL 如果远程仓库不止一个 还会将协作者一起列出来

1
2
3
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)

添加远程仓库

运行 git remote add <shortname> <url> 添加一个新的远程 Git 仓库 同时指定一个方便使用的简写

1
2
3
4
5
6
7
8
 git remote
origin
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)

如果想要拉取仓库的代码 使用 git fetch pb

1
git fetch pb

从远程仓库中抓取与拉取

从远程仓库中获取代码 可以执行

1
git fetch <remote>

这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。

如果你的当前分支设置了跟踪远程分支 那么可以用 git pull 命令来自动抓取后合并该远程分支到当前分支。

默认情况下,git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或其它名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。

推送到远程仓库

git push <remote> <branch>

1
git push origin master//将master分支推送到origin分支

查看某个远程仓库

git remote show <remote>

1
2
3
4
5
6
7
8
9
10
11
12
git remote show origin
* remote origin
Fetch URL: https://github.com/schacon/ticgit
Push URL: https://github.com/schacon/ticgit
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)

远程仓库的重命名与移除

git remote rename

1
2
3
4
$ git remote rename pb paul //将pb重命名未paul
$ git remote
origin
paul

值得注意的是这同样也会修改你所有远程跟踪的分支名字。 那些过去引用 pb/master 的现在会引用 paul/master

移除一个远程仓库

1
2
3
$ git remote remove paul
$ git remote
origin

一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。


文章作者: olddog
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 olddog !
  目录