git笔记
安装 Git
sudo dnf install git-all centOs基于 RPM 的发行版
sudo apt install git-all Ubuntu基于 Debian 的发行版
https://git-scm.com/download/win Windows 上安装
初次运行 Git 前的配置
查看配置
git config user.name 检查 Git 的某一项配置user.name为key名
git config --list 查看所有的配置
git config --list --show-origin 查看所有的配置以及它们所在的文件
用户信息:设置你的用户名和邮件地址,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
获取帮助
#任选其一
git help config
git add -h
git add --help
查看git命令的使用方法及说明的快捷方式
| git 命令 | 说明 |
|---|---|
| git init | 初始化仓库 |
| git clone | 克隆仓库 |
| git status | 查看文件状态 |
| git add | 添加文件到暂存区 |
| .gitignore | 忽略文件 |
| git diff | 查看修改之后还没有暂存起来的变化内容 |
| git commit | 提交更新 |
| git rm | 移除文件 |
| git mv | 移动文件 |
| git log | 查看提交历史 |
| git commit --amend | reset | checkout | 撤消操作 |
| git remote | 查看远程仓库 |
| git tag | 查看标签列表 |
| git config --global alias.ci commit | 配置别名 |
| git branch | 查看分支 |
| git rebase master | 变基到master分支 |
| git stash | 贮藏与清理 |
在已存在目录中初始化仓库↑↑↑
首先需要进入该项目目录中(命令cd进入目录或鼠标双击进入),之后执行:
git init
git init --bare 初始化一个空的仓库
如果在一个已存在文件的文件夹(而非空文件夹)中进行版本控制,通过以下命令进行跟踪:
git add .
git commit -m '备注'
克隆现有的仓库↑↑↑
克隆仓库的命令是 git clone
git clone https://github.com/libgit2
如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名:
git clone https://github.com/libgit2/libgit2 mylibgit
检查当前文件状态↑↑↑
git status 查看哪些文件处于什么状态
#如果是修改文件,则显示: modified: README(被修改的文件)
#如果是新添加文件,则显示: new file: README(新添加的文件)
【比较少用】
git status -s 简洁的方式查看更改 等效 git status --short
?? :新添加的未跟踪文件
A : 新添加到暂存区中的文件
M : 修改过的文件
跟踪新文件(暂存已修改的文件【添加到暂存区】)↑↑↑
git add CONTRIBUTING.md 添加指定文件到暂存区
git add . 添加所有文件到暂存区
忽略文件↑↑↑
我们总会有些文件无需纳入 Git 的管理,通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件。我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。
.gitignore 的格式规范如下:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(/)开头防止递归。
- 匹配模式可以以(/)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。
.gitignore 例子:
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件
第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件
要养成一开始就为你的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
glob 模式
指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。使用两个星号( **)表示匹配任意中间目录,比如 a/**/z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等。
.gitignore 文件的例子
# 忽略所有的 .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
在最简单的情况下,一个仓库可能只根目录下有一个 .gitignore 文件,它递归地应用到整个仓库中。 然而,子目录下也可以有额外的 .gitignore 文件。子目录中的 .gitignore 文件中的规则只作用于它所在的目录中。 (Linux 内核的源码库拥有 206 个 .gitignore 文件。)更多详情见 man gitignore。GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表, 你可以在 https://github.com/github/gitignore 找到它。
要查看尚未暂存的文件更新了哪些部分↑↑↑
git diff 此命令比较的是工作目录中当前文件和暂存区域快照之间的差异。 也就是修改之后还没有暂存起来的变化内容。
git diff --staged 查看已暂存的将要添加到下次提交里的内容,这条命令将比对已暂存文件与最后一次提交的文件差异。
git diff --cached 查看已经暂存起来的变化
请注意,git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你一下子暂存了所有更新过的文件,运行 git diff 后却什么也没有,就是这个原因。
提交更新↑↑↑
git commit 如何后面不加参数,会启动你选择的文本编辑器来输入提交说明。
可以在 commit 命令后添加 -m 选项,将提交信息与命令放在同一行,如下所示:
git commit -m "Story 182: Fix benchmarks for speed"
git commit -a -m 'added new benchmarks' 给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤(跳过使用暂存区域)
-a 选项使本次提交包含了所有修改过的文件。 这很方便,但是要小心,有时这个选项会将不需要的文件添加到提交中
移除文件↑↑↑
git rm 从已跟踪文件清单中移除(暂存区域移除)某个文件
连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。也可以简单地从工作目录中手工删除文件,然后再运行 git rm 记录此次移除文件。
如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f(译注:即 force 的首字母)
如果我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中(你想让文件保留在磁盘)使用 --cached 选项:
【任选其一】
git rm --cached README
#git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式
git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:
git rm \*~ 该命令会删除所有名字以 ~ 结尾的文件。
移动文件↑↑↑
git mv file_from file_to Git 中对文件改名(会智能识别是移动还是重命名)
相当于三条命令:
mv README.md README
git rm README.md
git add README
查看提交历史↑↑↑
git log 不传参数会按时间先后顺序列出所有提交(倒序)
git log -p 等效 git log --patch
git log -p -2 显示最近两次提交引入的差异(按 补丁 的格式输出)
git log --stat 每次提交的简略统计信息(有多少文件被修改...差异总结)
git log --pretty=oneline 将每个提交放在一行显示(还有 short,full 和 fuller 选项,它们展示信息的格式基本一致,但是详尽程度不一)
git log --pretty=format:"%h - %an, %ar : %s" 可以定制记录的显示格式
git log --pretty=format:"%h %s" --graph 使用 ASCII 字符串来形象地展示你的分支、合并历史
git log --since=2.weeks 列出最近两周的所有提交(可以类似"2008-01-15",还可以类似"2 years 1 day 3 minutes ago" )
git log -S function_name 接受一个字符串参数,找出添加或删除了对某一个特定函数的引用的提交
用 --author 选项显示指定作者的提交,用 --grep 选项搜索提交说明中的关键字。你可以指定多个 --author 和 --grep 搜索条件,这样会只输出 任意 匹配 --author 模式和 --grep 模式的提交。然而,如果你添加了 --all-match 选项, 则只会输出 所有 匹配 --grep 模式的提交。为了避免显示的合并提交弄乱历史记录,可以为 log 加上 --no-merges 选项。
Table 1. git log --pretty=format 常用的选项
| 选项 | 说明 |
|---|---|
| %H | 提交的完整哈希值 |
| %h | 提交的简写哈希值 |
| %T | 树的完整哈希值 |
| %t | 树的简写哈希值 |
| %P | 父提交的完整哈希值 |
| %an | 作者名字 |
| %ae | 作者修订日期(可以用 --date=选项 来定制格式) |
| %ar | 作者修订日期,按多久以前的方式显示 |
| %cn | 提交者的名字 |
| %ce | 提交者的电子邮件地址 |
| %cd | 提交日期 |
| %cr | 提交日期(距今多长时间) |
| %s | 提交说明 |
| 作者指的是实际作出修改的人,提交者指的是最后将此工作成果提交到仓库的人。 |
Table 2. 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 合用的简写。 |
Table 3. git log 的常用选项
| 选项 | 说明 |
|---|---|
| - |
仅显示最近的 n 条提交。 |
| --since, --after | 仅显示指定时间之后的提交。 |
| --until, --before | 仅显示指定时间之前的提交。 |
| --author | 仅显示作者匹配指定字符串的提交。 |
| --committer | 仅显示提交者匹配指定字符串的提交。 |
| --grep | 仅显示提交说明中包含指定字符串的提交。 |
| -S | 仅显示添加或删除内容匹配指定字符串的提交。 |
完整示例
git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/ 查看 Junio Hamano 在 2008 年 10 月其间, 除了合并提交之外的哪一个提交修改了测试文件
git log -- /f/idea_workspace/dev/chilin_kitchen_web/src/main/java/com/mieasy/kitchen/domain/KitchenOrder.java 可以在git log 选项的最后指定它们的路径(绝对路径【进入项目文件位置右键复制,然后在git命令窗口中右键粘贴】),因为是放在最后位置上的选项,所以用两个短划线(--)隔开
撤消操作↑↑↑
git commit --amend 暂存区中的文件提交。如果自上次提交以来你还未做任何修改,你所修改的只是提交信息
例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:
git commit -m 'initial commit'
git add forgotten_file
git commit --amend
最终你只会有一个提交——第二次提交将代替第一次提交的结果。
当你在修补最后的提交时,并不是通过用改进后的提交 原位替换 掉旧有提交的方式来修复的。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
取消暂存的文件
git status 命令会提示 git reset HEAD <file>... 取消暂存
git reset HEAD CONTRIBUTING.md 取消暂存 CONTRIBUTING.md 文件
git reset 确实是个危险的命令,如果加上了 --hard 选项则更是如此。 然而在上述场景中,工作目录中的文件尚未修改,因此相对安全一些。
撤消对文件的修改
git status 命令会提示 git checkout -- <file>... 撤消之前所做的修改【将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)】
git checkout -- CONTRIBUTING.md
git checkout --
远程仓库的使用↑↑↑
你完全可以在一个“远程”仓库上工作,而实际上它在你本地的主机上。 词语“远程”未必表示仓库在网络或互联网上的其它位置,而只是表示它在别处。 在这样的远程仓库上工作,仍然需要和其它远程仓库上一样的标准推送、拉取和抓取操作。
查看远程仓库
git remote 查看你已经配置的远程仓库服务器。origin ——这是 Git 给你克隆的仓库服务器的默认名字
git remote -v 显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL 示例如下:
origin chad@dev:/home/chad/public_git/chilin_kitchen_web.git (fetch)
origin chad@dev:/home/chad/public_git/chilin_kitchen_web.git (push)
添加远程仓库
git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写
示例如下:
git remote add pb https://github.com/paulboone/ticgit
git fetch pb 使用字符串 pb 来代替整个 URL拉取 Paul 的仓库中有但你没有的信息
从远程仓库中抓取与拉取
git fetch <remote> 从远程仓库中获得数据,同上
git fetch origin 抓取克隆(或上一次抓取)后新推送的所有工作
注意:git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
如果你的当前分支设置了跟踪远程分支,那么可以用 git pull 命令来自动抓取后合并该远程分支到当前分支。
推送到远程仓库
git push <remote> <branch> 推送到上游
示例:
git push origin master
克隆时通常会自动帮你设置好那两个名字
git push(当只有一个主分支时,可以简写)
注意:只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。当其他人先推送到上游时,必须先抓取他们的工作并将其合并进你的工作后才能推送。
查看某个远程仓库
git remote show <remote> 查看某一个远程仓库的更多信息
示例:
git remote show origin
克隆时通常会自动帮你设置好那两个名字
git push(当只有一个主分支时,可以简写)
注意:只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。当其他人先推送到上游时,必须先抓取他们的工作并将其合并进你的工作后才能推送。
远程仓库的重命名与移除
git remote rename pb paul 修改一个远程仓库的简写名,将 pb 重命名为 paul(自动修改所有关联引用)
git remote remove paul 或 git remote rm paul 移除一个远程仓库
打标签↑↑↑
git tag (可带上可选的 -l 选项 --list)
按照特定的模式查找标签
git tag -l "v1.8.5*"
如果你只想要完整的标签列表,那么运行 git tag 就会默认假定你想要一个列表,它会直接给你列出来, 此时的 -l 或 --list 是可选的。
然而,如果你提供了一个匹配标签名的通配模式,那么 -l 或 --list 就是强制使用的。
附注标签
附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签。
git tag -a v1.4 -m "my version 1.4"创建附注标签最简单的方式是当你在运行 tag 命令时指定 -a
-m 选项指定了一条将会存储在标签中的信息。 如果没有为附注标签指定一条信息,Git 会启动编辑器要求你输入信息
git show v1.4 可以看到标签信息和与之对应的提交信息
轻量标签
轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。本质上是将提交校验和存储到一个文件中——没有保存任何其他信息。创建轻量标签,不需要使用 -a、-s 或 -m 选项,只需要提供标签
git tag v1.4-lw
后期打标签
可以对过去的提交打标签,需要在命令的末尾指定提交的校验和(或部分校验和)
git tag -a v1.2 9fceb02
共享标签
默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。 这个过程就像共享远程分支一样——你可以运行 git push origin
git push origin v1.5
一次性推送很多标签,可以使用带有 --tags 选项的 git push 命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里。示例如下:
git push origin --tags
使用 git push
删除标签
git tag -d <tagname> 删除掉你本地仓库上的标签,示例如下:
git tag -d v1.4-lw
注意上述命令并不会从任何远程仓库中移除这个标签,你必须用 git push <remote> :refs/tags/<tagname> 来更新你的远程仓库,示例如下:
git push origin :refs/tags/v1.4-lw
或
git push origin --delete <tagname>
检出标签
如果你想查看某个标签所指向的文件版本,可以使用 git checkout 命令, 虽然这会使你的仓库处于“分离头指针(detached HEAD)”的状态——这个状态有些不好的副作用:
git checkout 2.0.0
在“分离头指针”状态下,如果你做了某些更改然后提交它们,标签不会发生变化, 但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问。 因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:
git checkout -b version2 v2.0.0
如果在这之后又进行了一次提交,version2 分支就会因为这个改动向前移动, 此时它就会和 v2.0.0 标签稍微有些不同,这时就要当心了。
Git 别名↑↑↑
git config --global alias.br commit
当要输入 git commit 时,只需要输入 git ci。
Git 分支
分支创建↑↑↑
git branch testing 创建一个 testing 分支
git log --oneline --decorate 查看各个分支当前所指的对象
git checkout testing 切换到一个已存在的分支
git log --oneline --decorate --graph --all 查看分叉历史
通常我们会在创建一个新分支后立即切换过去,这可以用 git checkout -b
分支的新建与合并
假设你的工作项目master 分支上已经有了一些提交,要解决你的公司使用的问题追踪系统中的 #53 问题。
git checkout -b iss53 新建一个分支并同时切换到那个分支上
它是下面两条命令的简写:
git branch iss53
git checkout iss53
iss53 分支在不断的向前推进,并且做了一些提交。现在你接到那个电话,有个紧急问题等待你来解决。你所要做的仅仅是切换回 master 分支。留意你的工作目录和暂存区里那些还没有被提交的修改, 它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支。假设你已经把你的修改全部提交了,切换回 master 分支
git checkout master
当你切换分支的时候,Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。
接下来建立一个 hotfix 分支:
git checkout -b hotfix
修改测试正确后将 hotfix 分支合并回你的 master 分支来部署到线上
git checkout master 切换到master分支
git merge hotfix 将hotfix分支合并到master分支上
“快进(fast-forward)”在合并的时候,由于两个不同的分支所指向的提交是同一个提交的直接后继,因此 Git 会直接将指针向前移动。(指针右移)
解决方案发布之后,你应该先删除 hotfix 分支,因为你已经不再需要它了 —— master 分支已经指向了同一个位置。
git branch -d hotfix
切换回你正在工作的分支继续你的工作,也就是针对 #53 问题的那个分支(iss53 分支)。
git checkout iss53
hotfix 分支上所做的工作并没有包含到 iss53 分支中。如果你需要拉取 hotfix 所做的修改,使用 git merge master 。
修正了 #53 问题,将 iss53 分支合并到master 分支,和之前你合并 hotfix 分支所做的工作差不多。
git checkout master
git merge iss53
Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的公共祖先(C2),做一个简单的三方合并。Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。
删除不再需要的 iss53 分支
git branch -d iss53
遇到冲突时的分支合并
两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。
git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:
git status
将冲突解决后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。
如果你想使用图形化工具来解决冲突,你可以运行 git mergetool,该命令会为你启动一个合适的可视化合并工具,等你退出合并工具之后,Git 会询问刚才的合并是否成功。 如果你回答是,Git 会暂存那些文件以表明冲突已解决: 你可以再次运行 git status 来确认所有的合并冲突都已被解决。
然后再提交
git commit -m 'YYY'
分支管理
git branch 不加任何参数运行会得到当前所有分支的一个列表
分支前的 * 字符:表示当前所在分支
git branch -v 查看每一个分支的最后一次提交
git branch --merged 查看已经合并到当前分支的分支
在这个列表中分支名字前没有 * 号的分支通常可以使用 git branch -d 删除掉
git branch --no-merged 查看未合并到当前分支的分支
git branch -d 命令删除它时会失败 例:git branch -d testing
可以使用 -D 选项强制删除它 例:git branch -D testing
git branch --no-merged master 查看分支未合并到master 分支的有哪些(可以先切换到指定分支 如:git checkout testing)
远程分支
git fetch <remote> (例:git fetch origin) 与给定的远程仓库同步数据
git push <remote> <branch>(例:git push origin serverfix) 将本地分支(当前所在分支)推送到远程仓库并创建分支【简化:serverfix:serverfix(refs/heads/serverfix:refs/heads/serverfix)】
git merge origin/serverfix 合并到当前所在的分支
git checkout -b serverfix origin/serverfix 在本地创建serverfix分支建立在远程跟踪分支之上
git branch -u origin/serverfix 修改正在跟踪的上游分支
git branch -vv 查看所有的本地分支
【ahead 2 意味着本地有两个提交还没有推送到服务器上。 behind 1 有一次提交还没有合并】
变基↑↑↑
git checkout experiment 切换到experiment分支
git rebase master 变基到 master 分支
git checkout master 切换到master分支
git merge experiment 合并experiment分支
git rebase --onto master server client 取出 client 分支,找出它从 server 分支分歧之后的补丁, 然后把这些补丁在 master 分支上重放一遍
git checkout master
git merge client
git rebase master server (git rebase <basebranch> <topicbranch> )将主题分支 (即本例中的 server)变基到目标分支(即 master)
git checkout master
git merge server
git branch -d client 删除client分支
git branch -d server 删除server分支
变基的风险:如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。
贮藏与清理↑↑↑
git stash 或 git stash push 贮藏修改
git stash list 查看贮藏的东西
git stash apply 贮藏的工作重新应用(默认为最近的贮藏)
git stash apply stash@{2} 应用指定的贮藏
git stash drop stash@{0} 删除指定的贮藏
浙公网安备 33010602011771号