Git 安装
Windows安装时需要注意在Configuring the line ending conversions
界面,选择Checkout as-is,commit as -s
,避免Windows的换行符问题。如果忘记设置,可以使用如下命令后期设置:
git config --global core.autocrlf false
参考:
Git 配置
可以通过 查看配置:
git config -l
git config --list [--local | --global | --system]
说明:
system
不常用local
需要在一个 Git 仓库下使用,它的配置,优先级是最高的。
设置 Git 账号
配置 user 信息
git config --global user.name "michael728"
git config --global user.email "[email protected]"
local
:区域为本仓库global
: 当前用户的所有仓库system
: 本系统的所有用户
运行 git config --help
可以看到帮助文档,比如,git config --unset usr.name
可以将 usr.name
删除,应该是 user.name
。
生成 SSH Key
- 生成 ssh 公钥时,不要重命名文件,否则会导致 ssh 方式下载代码库失败:
ssh-keygen -t rsa -C "[email protected]"
- 一个 ssh key 只能绑定在一个 Git 账户上,而一个 Git 账户可以绑定多个 ssh key。
- 公钥就相当于一个 fingerprint ,公钥和唯一一个 Git 账户绑定,那么凡是机器上有这个公钥对应的私钥,机器就有绑定账户的权限
- 在 A 机器上生成的私钥发送到 B 机器上,那么,B 机器也会有权限下载了
参考:
Git 配置别名
git config
文件来轻松为每一个命令设置别名。例如:
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 子命令,可以在命令前面加 !
符号。
演示将git visual定义为gitk的别名:
git config --global alias.visual '!gitk'
设置命令的别名,可以提高操作效率。查看.gitconfig
文件vim ~/.gitconfig
:
[user]
name = xxx
email = xxx
[i18n]
commitencoding = utf-8
logoutputencoding = utf-8
[core]
quotepath = false
[filter "lfs"]
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
required = true
[alias]
co = checkout
br = branch
c = commit
s = status
unstage = reset HEAD --
last = log -1 HEAD
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
[color]
ui = true
我们可以体验一个log的别名命令设置:
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
这是超厉害的别名缩写命令,试试现在的 git lg
有多酷炫吧!
探秘 .git 目录
.git
裸仓库文件夹,反映了 Git 良好的文件存储机制。
- HEAD 文件,指向当前所在的分支,表示一个「引用」。例如当前在 develop 分支,HEAD 内容就是
ref: refs/heads/develop
- config 文件,是本地仓库的配置文件,
git config --local --list
- refs 文件夹,包含了
heads
和tag
文件夹。heads
表示我们的分支,tag
标签,也叫做「里程碑」。- heads 文件夹下有多个文件,每个文件和仓库存在的分支名一样,文件内容是 commit id。文件当中存放的其实是这个分支的指针指向哪一个 commit id。
git branch -av
可以看到分支信息和 commit id。它是个commit
类型的对象。 - tags 中也有多个文件,文件名和存在 tag 名一致,内容也是 commit id。它是个
commit
类型的对象。
- heads 文件夹下有多个文件,每个文件和仓库存在的分支名一样,文件内容是 commit id。文件当中存放的其实是这个分支的指针指向哪一个 commit id。
- objects 文件夹(核心),存放所有的 git 对象,对象哈希值前 2 位作为文件夹名称,后 38 位作为对象文件名, 可通过
git cat-file -p <2位+38位>
命令查看文件内容。git cat-file -t <2位+38位>
查看对象类型,这是一个tree
类型的对象。内容本身是一个blob
对象。任何文件的内容相同,在 Git 眼里,它就是唯一的一个blob
对象。 - COMMIT_EDITMSG 文件
- ORIG_HEAD 文件,好像是上一次的 commit id
- description 文件,仓库的描述信息文件
- index 文件
- hooks 文件夹
- info 文件夹
- logs 文件夹
查看对象类型、对象内容、对象大小的命令:
git cat-file -t
命令 , 查看 git 对象的类型git cat-file -p
命令, 查看 git 对象的内容git cat-file -s
命令, 查看 git 对象的大小
Git 对象彼此关系
commit tree blob 三个对象之间的关系:
一次 commit id 对应一棵树(tree
),一次快照,整个项目的快照,包含了哪些文件夹(tree
)、哪些文件(blob
)。blob
可以看做是一个文件,但是和文件名是没关系的,不管文件名是什么,只要文件内容相同,就是一个 blob
,大大节约了存储空间。
实验
新建一个 git 仓库,创建一个 doc 文件夹,在 doc 文件夹中创建 readme 文件
- 在单纯创建 doc 文件夹时, git 不会理会
- 创建 readme 文件之后,会提示有文件可以添加跟踪
- 这时候执行
find .git/objects --type f
没有发现有对象生成 - 接着执行
git add doc
将文件添加到暂存区,这时候有文件对象生成了:
$ find .git/objects -type f
.git/objects/27/e826dc62c8a3616e7c15d45a3d77cd8e7966c0
$ git cat-file -t 27e8
blob
- 接着创建 commit,
git commit -m "add readme"
,这时候文件对象内容:
.git/objects/27/e826dc62c8a3616e7c15d45a3d77cd8e7966c0
.git/objects/87/0af27bedac0cf42d9a7637709e455fa7de7a7e
.git/objects/a0/3d66adf115035c521bc08509f54d867590a458
.git/objects/e6/b633ca37bf3532f87e833c8f765e07ea50cfe8
1 个 commit 对象,2 个 tree 对象,1 个 blob 对象。
为何会有2个 tree 对象呢,其中,整个工作目录是一个 tree 对象,工作目录下的 doc 文件夹对应了一个 tree 对象。
扩充:我又将之前 doc 文件夹的 readme 文件复制在仓库的根目录下,此时在 git add readme
之后,文件对象仍然无变化;但是,当 commit 之后,文件对象变多了,多了 1 个 commit,1个 tree 对象。这个多出来的 tree 对象,就是因为工作目录变化了,那么就多出来了一个 tree 对象。
Git 技巧
Git 帮助文档
授人以鱼不如授人以渔,先知道怎么通过帮助文档查看常用命令的说明吧:
git help
git help <cmd>
git help <cmd> --web # 使用浏览器页面打开
gitk 图形界面
gitk 后面可以跟上文件的路径, 这样能看单个文件的修改历史的具体内容。非常有用
- Patch 表示的是「变更集」,某一次 commit 修改的文件集合;
- Author 作者
- Commiter 提交人
- Cherry 挑选一个 commit,放到另一个分支上,这时候,Author 和 Commiter 就有可能不是一个人了,因为你挑选的那个 commit 作者可能是 A,你 cherry pick 过来之后提交,提交人是你,但是作者信息还是 A,版权考虑。
- Parent 上一次的 commit id
- Child 下一次的 commit id
- 菜单 View ,选择
All refs
可以看到所有的分支演变图
创建 Git 本地仓库
本地新建一个仓库
git init git_learning
已有远端仓库,创建本地仓库
git clone [email protected]:Michael728/michael-git.git
cd michael-git
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
已存在文件夹
cd micahel-git
git init
git remote add origin [email protected]:Michael728/michael-git.git
git add .
git commit
git push -u origin master
已存在 Git 仓库
cd existing_repo
git remote add origin [email protected]:Michael728/michael-git.git
git push -u origin --all # --all 表示 Push all branches,-u 选项指定了一个默认主机
git push -u origin --tags # --tags All refs under refs/tags are pushed
将本地的master
分支推送到origin
主机,同时指定origin
为默认主机,后面就可以不加任何参数使用git push
了。
参考: