我是靠谱客的博主 清爽世界,最近开发中收集的这篇文章主要介绍git教程 git笔记 git常用 git使用 git操作 git简明 git版本控制 git仓库git 使用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

git 使用

初次运行 Git 前的配置

查看、修改 gitconfig

git config --list --show-origin
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

记录每次更新到仓库

查看当前文件状态

git status
git status -s
# 状态简览

跟踪新文件或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等

git add README

查看未暂存或未提交差异

git diff
# 未暂存差异
git diff --cached (git diff --staged)
# 未提交差异

提交

git commit -m "add README.m"

移除文件

git rm README.m

从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中,比如忘记添加 .gitignore 文件

git rm --cached README
git rm --cached log/*.log
# 支持正则, 注意* 之前的反斜杠 ,因为 Git 有它自己的文件模式扩展匹配方式

移动文件

git mv file_from file_to
## 相当于
mv file_from file_to
git rm fire_from
git add file_to

查看提交历史

最近两次提交差异

git log -p -2

每次提交的简略的统计信息

git log --stat

不同于默认格式的方式展示提交历史,查看方式oneline, shortfullfuller 可以用

git log --pretty=oneline

定制显示记录格式 常用选项,(作者指的是实际作出修改的人,提交者指的是最后将此工作成果提交到仓库的人)

git log --pretty=format:"%h - %an, %ar : %s"

onelineformat 与另一个 log 选项 --graph 结合使用时尤其有用,形象地展示你的分支、合并历史

git log --pretty=format:"%h %s" --graph

git log 的 常用选项

限制输出长度,限制输出的选项

git log --since=2.weeks
# 最近两周的所有提交
git log -S function_name
# 找出添加或删除了对某一个特定函数的引用的提交
git log 1.txt 2.txt
# 某些文件或者目录的历史提交
git log -S function_name -- 1.txt
# 两个短划线隔开之前的选项和后面限定的路径名
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 commit --amend

取消暂存的文件

git restore --staged README.m
git reset HEAD README.m (老版本)

撤消对文件的修改,危险命令,你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它

git restore README.m
git checkout -- README.m (老版本)

远程仓库的使用

查看远程仓库

git remote
git remote -v
# 显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL

添加远程仓库,

git remote add <shortname> <url>
git remote add origin https://github.com/paulboone/ticgit

从远程仓库中抓取与拉取

git fetch <remote>
#必须注意 git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作
git pull <remote>
#如果你的当前分支设置了跟踪远程分支,自动抓取后合并该远程分支到当前分支

推送到远程仓库

git push <remote> <branch>
git push origin master
# 克隆时通常会自动帮你设置好那两个名字

查看某个远程仓库

git remote show <remote>

远程仓库的重命名与移除

git remote rename pb paul
# 重命名
git remote remove paul
# 移除

打标签

列出标签

git tag
git tag -l "v1.8.5*"
# 标签过滤

创建标签

轻量标签很像一个不会改变的分支——它只是某个特定提交的引用

而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。

git tag -a v1.4 -m "my version 1.4"
# 附注标签
git show v1.4
# 查看标签信息和与之对应的提交信息
git tag v1.4-lw
# 轻量标签
git tag -a v1.2 9fceb02
# 在某个提交上打标签

共享标签

git push origin v1.5
git push origin --tags
# 一次性推送很多标签

删除标签

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 2.0.0
# 会使你的仓库处于“分离头指针(detached HEAD)”的状态
git checkout -b version2 v2.0.0
# 如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支

Git 别名

git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
# 取消暂存文件
git config --global alias.last 'log -1 HEAD'
# 最后一次提交
git config --global alias.visual '!gitk'
# 执行外部命令,而不是一个Git子命令,命令前面加入!符号

分支新建与合并

分支创建

git branch testing
git log --oneline --decorate
# 查看各个分支当前所指的对象

分支切换

git checkout testing
git chekkout -b testing
# 创建一个新分支后立即切换过去,相当于 git branch,git checkout

查看分叉历史

git log --oneline --decorate --graph --all

删除分支

git branch -d hotfix

合并分支

git checkout master
# 检出到你想合并入的分支
git merge iss53
# 合并 iss53 分支到 master 分支

遇到冲突时的分支合并

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。

git mergetool
# 启动一个合适的可视化合并工具

分支管理

查看分支

git branch
# 分支的一个列表
git branch -v
# 查看每一个分支的最后一次提交
git branch --merged
# 哪些分支已经合并到当前分支, 这个列表中分支名字前没有*号的分支通常可以使用 git branch -d 删除掉
git branch --no-merged	# 尚未合并到当前分支
git branch --no-merged master
# 不必检出到 master, 查看未合并到 master 分支的有哪些

分支开发工作流

远程分支

查看远程分支

git ls-remote <remote>
# 获得远程引用的完整列表
git remote show <remote>
# 获得远程分支的更多信息

远程跟踪分支是远程分支状态的引用, 请将它们看做书签,它们以 <remote>/<branch> 的形式命名,例如 origin/master分支

同步数据

git fetch <remote>
# 从中抓取本地没有的数据,并且更新本地数据库,移动 origin/master 指针到更新之后的位置
git fetch origin

推送

git push <remote> <branch>
git push origin serverfix
# Git 自动将 serverfix 分支名字展开为 refs/heads/serverfix:refs/heads/serverfix
git push origin serverfix:serverfix
# 也可以运行, 推送本地的 serverfix 分支,将其作为远程仓库的 serverfix 分支
git push origin serverfix:awesomebranch # 本地的 serverfix 分支推送到远程仓库上的 awesomebranch 分支

可以运行 git merge origin/serverfix 将这些工作合并到当前所在的分支。 如果想要在自己的 serverfix 分支上工作,可以将其建立在远程跟踪分支之上

git checkout -b serverfix origin/serverfix

跟踪分支

git checkout -b <branch> <remote>/<branch>
git checkout --track origin/serverfix
# Git 提供了 --track 快捷方式
git checkout serverfix
# 如果你尝试检出的分支 (a) 不存在且 (b) 刚好只有一个名字与之匹配的远程分支,那么 Git 就会为你创建一个跟踪分支
git checkout -b sf origin/serverfix
# 如果想要将本地分支与远程分支设置为不同的名字
git branch -u origin/serverfix
# 设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支, 你可以在任意时间使用 -u 或 --set-upstream-to 选项运行 git branch 来显式地设置
# git merge @{u} 来取代 git merge origin/master

查看设置的所有跟踪分支

git branch -vv
git fetch --all; git branch -vv
# 统计最新的领先与落后数字,需要在运行此命令前抓取所有的远程仓库

拉取

git fetch # 从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容
git pull
#
在大多数情况下它的含义是一个 git fetch 紧接着一个 git merge 命令

删除远程分支

git push origin --delete serverfix
# 只是从服务器上移除这个指针, Git 服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。

变基

提取在 C4 中引入的补丁和修改,然后在 C3 的基础上应用一次,变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。

git checkout experiment
# 检出 experiment 分支, 将它变基到 master 分支上
git rebase master
git checkout master
# 回到 master 分支,进行一次快进合并
git merge experiment

在对两个分支进行变基时,所生成的“重放”并不一定要在目标分支上应用,你也可以指定另外的一个分支进行应用

将 client 中的修改合并到主分支并发布,但暂时并不想合并 server 中的修改

git rebase --onto master server client
#
取出 client 分支,找出它从 server 分支分歧之后的补丁, 然后把这些补丁在 master 分支上重放一遍,让 client 看起来像直接基于 master 修改一样

直接将主题分支 (即本例中的 server)变基到目标分支(即 master)上。 这样做能省去你先切换到 server 分支,再对其执行变基命令的多个步骤

git rebase <basebranch> <topicbranch>
git rebase master server

变基的风险

如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基

变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。

解决方法用变基解决变基

另一种简单的方法是使用 git pull --rebase 命令而不是直接 git pull。 又或者你可以自己手动完成这个过程,先 git fetch,再 git rebase teamone/master

如果你习惯使用 git pull ,同时又希望默认使用选项 --rebase,你可以执行这条语句 git config --global pull.rebase true 来更改 pull.rebase 的默认配置

只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作。

向一个项目贡献

git diff --check
# 找到可能的空白错误并将它们为你列出来
git add --patch
# 部分暂存文件
git format-patch -M origin/master
# 创建补丁, -M 开关告诉 Git 查找重命名

维护项目

git apply --check 0001-seeing-if-this-helps-the-gem.patch
# 检查补丁是否可以顺利应用
git apply /tmp/patch-ruby-client.patch
#	应用一个使用 git diff 生成补丁
## 建议使用 git format-patch 打补丁
git am 0001-limit-log-function.patch
# 应用一个由 format-patch 命令生成的补丁
git am --resolved
# 解决冲突后继续应用下一个补丁
git am -3 0001-seeing-if-this-helps-the-gem.patch
#
-3 选项来使 Git 尝试进行三方合并
git am -3 -i mbox
# 交互模式下运行 am 命令
git log contrib --not master
# 查看每次提交所引入的具体修改
git diff master...contrib
# 该分支与 master 分支的共同祖先进行比较
git cherry-pick e43a6
# 将提交 e43a6 拉取到 master 分支

准备一次发布

git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
# 最新的快照归档
git archive master --prefix='project/' --format=zip > `git describe master`.zip # 创建一个 zip 压缩包

提交简报

git shortlog --no-merges master --not v1.0.1
#自 v1.0.1 以来的所有提交

选择修订版本

简短的 SHA-1

git log --abbrev-commit --pretty=oneline

分支引用

git show topic1
# 假设 topic1 分支指向提交 ca82a6d...
git rev-parse topic1
# 某个分支指向哪个特定的 SHA-1

引用日志, 引用日志只存在于本地仓库

git reflog
git show HEAD@{5}
# HEAD 在五次前的所指向的提交
git show master@{yesterday}
# master 分支在昨天的时候指向了哪个提交
git log -g master
# git log 输出格式的引用日志信息

祖先引用

git show HEAD^
# 该引用的上一个提交
git show HEAD^^
# HEAD的父提交的父提交
git show HEAD^2
#	HEAD的第二父提交, 这个语法只适用于合并的提交,因为合并提交会有多个父提交
# 另一种指明祖先提交的方法是 ~
git show HEAD~2
# 代表“第一父提交的第一父提交”
# 组合使用
git show HEAD~3^2
# 来取得之前引用的第二父提交(假设它是一个合并提交)

提交区间

## 双点
git log master..experiment
# 在 experiment 分支中而不在 master 分支中的提交
git log origin/master..HEAD
# 查看你即将推送到远端的内容
# 下列三个命令是等价
git log refA..refB
git log ^refA refB
git log refB --not refA
## 多点
git log refA refB ^refC
# 被 refA 或 refB 包含的但是不被 refC 包含的提交
git log refA refB --not refC
## 三点
git log master...experiment
# master 或者 experiment 中包含的但不是两者共有的提交
git log --left-right master...experiment
# 它会显示每个提交到底处于哪一侧的分支

交互式暂存

git add -i
# --interactive

暂存补丁

git add -p
# --patch, 通常情况下可以输入 y 或 n 来选择是否要暂存每一个区

更进一步地,可以使用 git reset --patch 命令的补丁模式来部分重置文件, 通过 git checkout --patch 命令来部分检出文件与 git stash save --patch 命令来部分暂存文件

贮藏与清理

贮藏工作

git stash 或 git stash push
# 贮藏
git stash list
# 查看贮藏的东西
git stash apply
# 刚刚贮藏的工作重新应用
git stash apply stash@{2}
# 应用其中一个更旧的贮藏
git stash apply --index
# 尝试重新应用暂存的修改
git stash drop
# 移除的贮藏
git stash pop
# 应用贮藏然后立即从栈上扔掉它

贮藏的创意性使用

git stash --keep-index
# 不贮藏已暂存的内容
git stash -u
# --include-untracked, 藏任何未跟踪文件
git stash --patch
# 交互式地提示哪些改动想要贮藏

从贮藏创建一个分支

git stash branch testchanges

清理工作目录

git stash --all
# 更安全的移除每一样东西并存放在栈中
git clean
# 去除冗余文件或者清理工作目录
git clean -f -d
# 移除工作目录中所有未追踪的文件以及空的子目录
git clean -d -n
# 做一次演习然后告诉你 将要 移除什么

搜索

Git Grep 不仅仅可以可以搜索工作目录,还可以搜索任意的 Git 树

git grep -n gmtime_r
# -n 或 --line-number 选项数来输出 Git 找到的匹配行的行号
git grep --count gmtime_r
# -c 或 --count 仅包括那些包含匹配字符串的文件,以及每个文件中包含了多少个匹配
git grep -p gmtime_r *.c
#
-p 或 --show-function 选项来显示每一个匹配的字符串所在的方法或函数
git grep --break --heading 
-n -e '#define' --and ( -e LINK -e BUF_MAX ) v1.8.0
# 查看在旧版本 1.8.0 的 Git 代码库中定义了常量名包含 “LINK” 或者 “BUF_MAX” 这两个字符串的行 (这里也用到了 --break 和 --heading 选项来使输出更加容易阅读)

Git 日志搜索

git log -S ZLIB_BUF_MAX --oneline
# 找到 ZLIB_BUF_MAX 常量是什么时候引入的
# 你可以使用 -G 选项来使用正则表达式搜索

行日志搜索

git log -L :git_deflate_bound:zlib.c
# 展示代码中一行或者一个函数的历史
git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c	# 提供一个正则表达式

重写历史

修改最后一次提交,修正会改变提交的 SHA-1 校验和。 它类似于一个小的变基

git commit --amend
git commit --amend --no-edit
# 避免不必要的编辑器环节

修改多个提交信息

git rebase -i HEAD~3
# 从上到下的依次重演每一个提交引入的修改,每一个修改了提交信息的提交及其 所有后裔都会被重写

重新排序提交,压缩提交,拆分提交

git rebase -i HEAD~3
# 后修改顺序
# squash 压缩提交
# edit 然后 git reset HEAD^, 几个提交后,运行 git rebase --continue

核武器级选项:filter-branch

想要通过脚本的方式改写大量提交的话可以使用它——例如,全局修改你的邮箱地址或从每一个提交中移除一个文件,git filter-branch 有很多陷阱,不再推荐使用它来重写历史。 请考虑使用 git-filter-repo,它是一个 Python 脚本,相比大多数使用 filter-branch 的应用来说,它做得要更好。它的文档和源码可访问 https://github.com/newren/git-filter-repo 获取。

git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# 从整个提交历史中移除一个叫做 passwords.txt 的文件, 为了让 filter-branch 在所有分支上运行,可以给命令传递 --all 选项

使一个子目录做为新的根目录

git filter-branch --subdirectory-filter trunk HEAD
# 让 trunk 子目录作为每一个提交的新的项目根目录

全局修改邮箱地址

git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD

重置揭密

git cat-file -p HEAD
# 底层命令
git ls-tree -r HEAD
git ls-files -s

重置的作用

git reset --soft HEAD~
# 把该分支移动回原来的位置,而不会改变索引和工作目录
git reset --mixed HEAD~
# 默认,它依然会撤销一上次 提交,但还会 取消暂存 所有的东西
git reset --hard HEAD~
# 让工作目录看起来像索引

通过路径来重置

git reset file.txt
# 其实是 git reset --mixed HEAD file.txt 的简写, 本质上只是将 file.txt 从 HEAD 复制到索引中,还有 取消暂存文件 的实际效果
git reset eb43bf file.txt
# 指定一个提交来拉取该文件的对应版本, 又可以运行 git add 添加它,也可以接受一个 --patch 选项来一块一块地取消暂存的内容。 这样你就可以根据选择来取消暂存或恢复内容了

压缩

git reset --soft HEAD~2
git commit

检出

不带路径

运行 git checkout [branch] 与运行 git reset --hard [branch] 非常相似,它会更新所有三棵树使其看起来像 [branch],不过有两点重要的区别

  1. checkout 对工作目录是安全的

  2. reset 会移动 HEAD 分支的指向,而 checkout 只会移动 HEAD 自身来指向另一个分支。

带路径

运行 checkout 的另一种方式就是指定一个文件路径,这会像 reset 一样不会移动 HEAD。 它就像 git reset [branch] file 那样用该次提交中的那个文件来更新索引,但是它也会覆盖工作目录中对应的文件。它就像是 git reset --hard [branch] file(如果 reset 允许你这样运行的话), 这样对工作目录并不安全,它也不会移动 HEAD

高级合并

合并冲突

git merge --abort
# 简单地退出合并
git reset --hard HEAD
# 回到上一次提交的状态

忽略空白

git merge -Xignore-space-change whitespace
# 这次使用 -Xignore-all-space 或 -Xignore-space-change 选项。 第一个选项在比较行时 完全忽略 空白修改,第二个选项将一个空白符与多个连续的空白字符视作等价的

手动文件再合并

git show :1:hello.rb > hello.common.rb
# Stage 1 是它们共同的祖先版本
git show :2:hello.rb > hello.ours.rb
# stage 2 是你的版本
git show :3:hello.rb > hello.theirs.rb
# stage 3 你将要合并入的版本(“theirs”)
git ls-files -u
# 使用 ls-files -u 底层命令来得到这些文件的 Git blob 对象的实际 SHA-1 值
# 手动修改 hello.theirs.rb 文件
git merge-file -p 
hello.ours.rb hello.common.rb hello.theirs.rb > hello.rb
# 命令来重新合并
git diff --ours
# 看看合并引入了什么
git diff --theirs	-b
# 合并的结果与他们那边有什么不同, -b 来去除空白
git diff --base
# 查看文件在两边是如何改动的
git clean -f
# 清理我们为手动合并而创建但不再有用的额外文件

检出冲

git checkout --conflict=diff3 hello.rb
# 重新检出文件并替换合并冲突标记
git checkout --ours 和 --theirs
# 选择留下一边, 当有二进制文件冲突时这可能会特别有用

合并日志

 git log --oneline --left-right HEAD...MERGE_HEAD
# 得到此次合并中包含的每一个分支的所有独立提交的列表
git log --oneline --left-right --merge
# 显示任何一边接触了合并冲突文件的提交
git log --oneline --left-right -p
# 得到所有冲突文件的区别

组合式差异格式

git diff
git log --cc -p -1
# 查看冲突是如何解决的

撤消合并

# 方法1: 修复引用
git reset --hard HEAD~
# 方法的缺点是它会重写历史,应当避免使用 reset
# 方法2: 还原提交
git revert -m 1 HEAD
# -m 1 标记指出 “mainline” 需要被保留下来的父结点
git revert ^M
# 如果重新 git merge topic 了

其他类型的合并

git merge -Xours mundo
# 使用 ours 快速合并
git merge-file --ours
# 来合并单个文件
git merge -s ours mundo
# 本质上会做一次假的合并
git diff HEAD HEAD~

子树合并

Rerere

重用记录的解决方案

git config --global rerere.enabled true
# 你也可以通过在特定的仓库中创建 .git/rr-cache 目录来开启它
git rerere status
# 通过 git rerere status 告诉你它记录的合并前状态
git rerere diff
# 显示解决方案的当前状态——开始解决前与解决后的样子
git ls-files -u
# 查看冲突文件的之前、左边与右边版本
# 修改解决,然后 commit
git reset --hard HEAD^
# 来回滚分支,然后 checkout 另外一个分支
git rebase master
# 得到了相同的合并冲突, 我们看这个文件,会发现它已经被解决了
git checkout --conflict=merge hello.rb
# 重新恢复到冲突时候的文件状态

使用 Git 调试

文件标注

git blame -L 69,82 Makefile
# 第 69 行到第 82 行每一行分别来自哪个提交和提交者
git blame -C -L 141,153 GITPackUpload.m # 看到代码块的原始出处

二分查找

git bisect start
# 来启动
git bisect bad
# 告诉系统当前你所在的提交是有问题的
git bisect good v1.0
# 告诉 bisect 已知的最后一次正常状态是哪次提交
git bisect good
# 来告诉 Git测试结果是没有问题的, 然后继续寻找
git bisect bad
# 发现这个提交下是有问题的
git bisect reset
# 最后,重置你的 HEAD 指针到最开始的位置
git bisect start HEAD v1.0
# 参数来设定这两个提交,第一个参数是项目不正常的提交,第二个参数是项目正常的提交
git bisect run test-error.sh
# Git 会自动在每个被检出的提交里执行 test-error.sh, 脚本在项目是正常的情况下返回 0,在不正常的情况下返回非 0

子模块

开始使用子模块

git submodule add https://github.com/chaconinc/DbConnector # 后面加上想要跟踪的项目的相对或绝对 URL 来添加新的子模块
git diff --cached --submodule
# 查看另一个是项目文件夹记录

克隆含有子模块的项目

git submodule init
# 用来初始化本地配置文件
git submodule update
# 从该项目中抓取所有数据并检出父项目中列出的合适的提交
git clone --recurse-submodules https:// # 自动初始化并更新仓库中的每一个子模块
git submodule update --init --recursive # 还要初始化、抓取并检出任何嵌套的子模块

在包含子模块的项目上工作

git fetch
# 进入到子目录中
git merge
git diff --submodule	# 进入主目录
git config --global diff.submodule log
# 不想每次输入 --submodle
git submodule update --remote DbConnector # 不想在子目录中手动抓取与合并

未完…

打包

git bundle create repo.bundle HEAD master
# 打包
git clone repo.bundle repo
# 接收者使用
git bundle create commits.bundle master ^9a466c5	# 打包区间
git bundle verify ../commits.bundle
# 检查这个文件是否是一个合法的 Git 包
git bundle list-heads ../commits.bundle
#
查看这边包里可以导入哪些分支
git fetch ../commits.bundle master:other-master # 可以使用 fetch 或者 pull 命令从包中导入提交

替换

凭证存储

配置 Git

 git config --global commit.template ~/.gitmessage.txt
# 模版

格式化与多余的空白字符

默认被打开的三个选项是:

blank-at-eol,查找行尾的空格;

blank-at-eof,盯住文件底部的空行;

space-before-tab,警惕行头 tab 前面的空格。

默认被关闭的三个选项是:

indent-with-non-tab,揪出以空格而非 tab 开头的行(你可以用 tabwidth 选项控制它);

tab-in-indent,监视在行头表示缩进的 tab;

cr-at-eol,告诉 Git 忽略行尾的回车。

git config --global core.autocrlf true
# 提交时自动地把回车和换行转换成换行,而在检出代码时把换行转换成回车和换行
git config --global core.autocrlf input
# 提交时把回车和换行转换成换行,检出时不转换
git config --global core.whitespace 
trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol # 不指定它或在它前面加个 -
git apply --whitespace=warn <patch>
# 探测到这些问题
git apply --whitespace=fix <patch>
# 自动修正此问题

服务器端配置

Git 属性

Git 钩子

底层命令与上层命令

Git 是一个内容寻址(content-addressable)文件系统。

config
# 包含项目特有的配置选项
description
# 仅供 GitWeb 程序使用,我们无需关心
HEAD
# 指向目前被检出的分支
(**重要**)
hooks/
# 包含客户端或服务端的钩子脚本(hook scripts
info/
# 包含一个全局性排除(global exclude)文件
objects/
# 存储所有数据内容
(**重要**)
refs/
# 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针
(**重要**)
#(尚待创建的)index 文件保存暂存区信息
(**重要**)

Git 对象

echo 'test content' | git hash-object -w --stdin
# 创建一个新的数据对象并将它手动存入你的新 Git 数据库中
git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4 # 取回数据
# 对一个文件进行简单的版本控制
echo 'version 1' > test.txt
git hash-object -w test.txt
echo 'version 2' > test.txt
# 写入新内容
git hash-object -w test.txt
git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt # 从对象数据库中取回它的第一个版本
# 记住文件的每一个版本所对应的 SHA-1 值并不现实, 文件名并没有被保存——我们仅保存了文件的内容
git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a # 告诉我们其内部存储的任何对象类型

树对象

git cat-file -p master^{tree}
# master 分支上最新的提交所指向的树对象
git update-index --add --cacheinfo 100644 
83baae61804e65cc73a7201a7252750c76066a30 test.txt
# 通过暂存一些文件来创建一个暂存区
git write-tree
# 将暂存区内容写入一个树对象
git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579 # 把树对象读入暂存区, 可以通过对该命令指定 --prefix 选项,将一个已有的树对象作为子树读入暂存区

提交对象

echo 'first commit' | git commit-tree d8329f
# 创建一个提交对象, 它先指定一个顶层树对象,代表当前项目快照
git log --stat 1a410e

这就是每次我们运行 git addgit commit 命令时,Git 所做的工作实质就是将被改写的文件保存为数据对象, 更新暂存区,记录树对象,最后创建一个指明了顶层树对象和父提交的提交对象。

对象存储

Git 是如何存储其对象的

Git 引用

这基本就是 Git 分支的本质:一个指向某一系列提交之首的指针或引用

echo 1a410efbd13591db07496601ebc7a059dd55cfe9 > .git/refs/heads/master # 创建一个新引用来帮助记忆最新提交所在的位置, 从技术上讲我们只需简单地做如下操作
git log --pretty=oneline master
git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9 # 更安全
git update-ref refs/heads/test cac0ca
# 第二个提交上创建一个分支

HEAD 引用

git symbolic-ref HEAD
refs/heads/test
# 可以手动编辑该文件, 可以借助此命令来查看 HEAD 引用对应的值

标签引用

git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d # 像这样创建一个轻量标签
git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag' # 若要创建一个附注标签,Git 会创建一个标签对象,并记录一个引用来指向该标签对象,而不是直接指向提交对象

远程引用

远程引用和分支(位于 refs/heads 目录下的引用)之间最主要的区别在于,远程引用是只读的

包文件

Git 会时不时地将多个这些对象打包成一个称为“包文件(packfile)”的二进制文件,以节省空间和提高效率。 当版本库中有太多的松散对象,或者你手动执行 git gc 命令,或者你向远程服务器执行推送时,Git 都会这样做。 要看到打包过程,你可以手动执行 git gc 命令让 Git 对对象进行打包

git gc

Git 是如何做到这点的? Git 打包对象时,会查找命名及大小相近的文件,并只保存文件不同版本之间的差异内容。 你可以查看包文件,观察它是如何节省空间的。 git verify-pack 这个底层命令可以让你查看已打包的内容:

git verify-pack -v .git/objects/pack/pack-978e03944f5c581011e6998cd0e9e30000905586.idx

引用规范

传输协议

维护与数据恢复

git reset --hard 1a410efbd13591db07 # 硬重置丢失数据
git reflog
# 引用日志
git branch recover-branch ab1afef	# 创建一个新的分支指向这个提交来恢复它
rm -Rf .git/logs/ #
如果已经没有引用日志了
git fsck --full
# 检查数据库的完整性, 显示出所有没有被其他对象指向的对象

移除对象

git rm git.tgz
# 移除大文件
git count-objects -v
# 快速的查看占用空间大小, size-pack 的数值指的是你的包文件以 KB 为单位计算的大小
git verify-pack -v .git/objects/pack/pack-29…69.idx
| sort -k 3 -n | tail -3 # 如果你执行 git gc 命令,所有的对象将被放入一个包文件中,你可以通过运行 git verify-pack 命令, 然后对输出内容的第三列(即文件大小)进行排序,从而找出这个大文件。
git rev-list --objects --all | grep 82c99a3
# 找出具体是哪个文件
git log --oneline --branches -- git.tgz
# 查看哪些提交对这个文件产生改动
git filter-branch --index-filter 'git rm --ignore-unmatch --cached git.tgz' -- 7b30847^.. # 重写 7b30847 提交之后的所有提交来从 Git 历史中完全移除这个文件
rm -Rf .git/refs/original
# 通过 filter-branch 选项添加的新引用中还存有对这个文件的引用
rm -Rf .git/logs/
# 删除引用日志
git gc
# 重新打包
git count-objects -v # 可以从 size 的值看出,这个大文件还在你的松散对象中,并没有消失;但是它不会在推送或接下来的克隆中出现,这才是最重要的
git prune --expire now
# 完全地移除那个对象

环境变量

来自:git官网

最后

以上就是清爽世界为你收集整理的git教程 git笔记 git常用 git使用 git操作 git简明 git版本控制 git仓库git 使用的全部内容,希望文章能够帮你解决git教程 git笔记 git常用 git使用 git操作 git简明 git版本控制 git仓库git 使用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部