Git基础教程
教程的测试环境为win10
安装
Windows下的Git安装一般有两种方式:
- 通过Cygwin模拟环境,安装Git工具。
- 安装打包好的Git环境。其中包括linux下常用的命令和Git,比较方便。
windows下推荐使用安装,方便快捷。
配置
在正式使用Git进行代码管理之前,需要配置用户名和邮箱信息,告诉git库是谁进行的操作。配置命令如下:
# 配置单项目用户名git config user.name "gitdemo"# 配置单项目用户邮箱git config user.email "gitdemo@51starcard.com"# 配置全局用户名git config --global user.name "gitdemo"# 配置全局用户邮箱git config --global user.email "gitdemo@51starcard.com"
单项目的配置值将会保存在
.git/config
文件中,全局配置一般存储在~/.gitconfig
文件中。另外还可以通过环境变量GIT_AUTHOR_NAME
和GIT_AUTHOR_EMAIL
值来实现用户信息配置。
创建初始版本库
Git可以正确使用的条件就是存在使用git管理的代码库,更直白的理解就是必须存在.git
目录。创建.git
目录即创建初始版本库的命令如下:
# 以gitdemo演示# 创建代码存储目录mkdir gitdemo# 创建初始版本库git init
关于版本库,Git中区分为开发版本库(一般使用的库)和裸版本库,二者主要的区别在于裸版本库不包含工作目录,而开发版本库则包含工作目录。二者详细的区别和应用可以参考博文。
开发
在初始版本库创建完成之后,就可以进行开发了。一般在开发时,都会根据代码的不同功能创建相应的分支,然后再分支上完成相应的开发。在开发和测试完成之后,在合并到master分支。为了后续的代码管理方便,一般不建议直接在master分支上直接进行开发。
-
暂存修改
完成代码编写后,首先需要暂存修改,其中包括保存已追踪文件的修改和未追踪文件添加并保存修改。# 保存当前目录下的所有修改和未追踪文件# 若目标为目录,git会自动递归所有文件git add .
-
提交修改 确认所有代码都正常之后就可以使用commit命令提交代码了。
# 每一次提交必须要有相关说明git commit -m "一些说明"
上面的暂存修改和提交修改可以直接通过
git commit -am '一些说明'
完成。需要注意的是这样会直接提交工作目录中的所有修改,除非确定提交所有,一般不建议使用。
git中的文件状态分为如下三类:
- 已追踪文件,指已经在版本库中的文件,或者已暂存到索引中的文件。
- 忽略文件,由.gitignore声明的项目中不需要进行管理的文件。
- 未追踪文件,指除去已追踪和忽略文件之后,剩余的文件。
分支的相关操作将会在后面专门介绍。
以上就是一般的git使用过程。
Git文件操作
- 添加文件 Git通过
add
命令将新添加的未追踪的文件添加到代码库中。常见参数说明:
# git add -husage: git add [] [--] ... -n, --dry-run 以演习得方式操作 -v, --verbose 列出详细信息 -i, --interactive 交互模式添加文件 -p, --patch 交互的方式批量添加 -e, --edit 编辑当前修改并应用 -f, --force 强制添加被忽略的文件 -u, --update 仅添加已追踪的文件 -N, --intent-to-add 仅记录会添加的目录 -A, --all 添加所有追踪的和未追踪文件的修改 --ignore-removal 忽略工作目录中已删除的目录 --refresh 仅刷新索引不执行添加操作 --ignore-errors 忽略文件中错误 --ignore-missing 检查在演习模式下文件是否被忽略了 --chmod <(+/-)x> 文件权限修改
- 删除文件 Git通过
rm
命令删除版本库中已追踪的文件,该命令会同时删除工作目录和版本库中的文件。另外需要注意的是,从工作目录和索引中删除一个文件,并不会删除该文件在版本库中的历史记录。要将一个文件由已追踪状态转换为未追踪状态,可以使用git rm --cached
命令。
# git rm -husage: git rm [] [--] ... -n, --dry-run 以演习得方式操作 -q, --quiet 不显示被删除的文件 --cached 仅从索引中删除该文件 -f, --force 忽略文件最新版本检查,强制删除 -r 允许递归删除 --ignore-unmatch 即使未匹配任何文件,也不报错
- 文件移动(重命名) 对于文件的重命名或者移动,可以通过组合
git rm
和git add
命令实现,也可以通过git mv
命令来实现。两种方式的操作结果最终是一样的,更新索引并重新关联到原对象。
# git mv -husage: git mv []
- .gitignore文件说明 Git可以通过
.gitignore
忽略任何文件。一般可以通过将想要忽略的文件名添加到该目录下的.gitignore
文件中或者将该文件添加到顶层目录中的.gitignore
中。.gitignore
规则如下:- 空行会被忽略,以#好开头的行可以用于注释。
- 一个简单的字面值文件名匹配任何目录中的同名文件。
- 目录名由末尾的反斜杠标记,能匹配同名的目录和子目录,但是不能匹配文件或符号链接。
- 包含shell通配符,此种模式可以扩展未shell通配模式。
- 启示的感叹号会对该行其余部分的模式进行取反。取反模式会覆盖低优先级的规则。
常见的
.gitignore
规则可以参考。
Git分支管理
Git相比于其它的版本控制工具,其中一大优势就在与分支操作和管理的方便快捷。恰当的使用Git的分支管理功能会大幅提高团队开发的效率,同时减少多人同时修改同一文件发生错误的次数。
-
创建分支
git branch
命令可创建分支,相关语法和参数如下:# git branch -husage: git branch [
] [-r | -a] [--merged | --no-merged]or: git branch [ ] [-l] [-f] [ ]or: git branch [ ] [-r] (-d | -D) ...or: git branch [ ] (-m | -M) [ ] or: git branch [ ] [-r | -a] [--points-at]Generic options-v, --verbose 显示详细信息-q, --quiet 不提示消息-t, --track 设置未追踪模式--set-upstream 设置上游信息-u, --set-upstream-to 设置上游--unset-upstream 取消上游设置--color[= ] 输出着色-r, --remotes 在远程仓库分支执行--contains 仅显示包含指定提交的分支--abbrev[= ] 以n位字节显示sha1值Specific git-branch actions:-a, --all 显示远程和本地分支-d, --delete 删除已合并分支-D 删除并未合并的分支-m, --move 移动或重命名分支-M 强制移动或重命名分支--list 列出分支名称-l, --create-reflog 创建分支的引用历史--edit-description 编辑分支的说明-f, --force 强制执行创建,移动,删除等操作--merged 列出已合并分支--no-merged 列出未合并分支--column[= 一般而言创建分支命令为:
# 从当前提交创建分支devgit branch dev# 从ft/gitdemo提交创建分支devgit branch dev ft/gitdemo
-
删除分支
# 删除已合并dev分支git branch -d dev# 删除未合并dev分支git branch -D dev
-
检出分支
Git的工作目录一次只能反映一个分支,要在不同的分支上进行工作,就需要使用git checkout
命令进行检出。git checkout
改变了工作树文件和目录结构。# 创建bug/pr-01分支git branch bug/pr-01# 检出到bug/pr-01分支git checkout bug/pr-01
usage: git checkout [
] or: git checkout [ ] [ ] -- ...-q, --quiet 不显示进度信息-b 创建并检出该分支-B 创建或重置,并检出该分支-l 为新分支创建引用历史--detach detach HEAD at named commit-t, --track 设置分支的上游信息--orphan 新分支无父对象-2, --ours checkout our version for unmerged files-3, --theirs checkout their version for unmerged files-f, --force 强制检出分支-m, --merge 对待检出分支执行合并操作--overwrite-ignore 更新忽略的文件--conflict
在有未提交的内容时,执行检出操作,若是工作目录中的未被追踪的文件,则会置之不理,若是一个文件的修改不同与待检出分支上的内容,则Git会报错并结束检出操作。对于存在冲突的情况可以使用
-m
参数来执行合并操作,在检出完成之后再解决冲突。
-
分支合并
git中合并分支有git merge
和git rebase
两个命令。- merge操作 merge的流程一般是,寻找两个分支的共同祖先,然后进行三方比较,生成合并后的内容。
- rebase操作 rebase操作流程一般是寻找到两个分支的祖先,比较得出待合并分支的变化内容,接着在base分支上将变化内容执行一遍,生产合并后的内容。
merge和rebase合并操作得到的结果理论上来说是一样的,但是二者生成的log记录是不同的,rebase命令的更加清晰,为单条主线演进,而merge则为多条分支演进,理解桑也较为繁琐。
usage: git merge [
] [ ...]or: git merge [ ] HEAD or: git merge --abort-n 不显示受影响的地方--stat 显示受影响的地方--summary 等同于 --stat--log[= ] 添加简短的日志的commit的说明中--squash 已commit的方式替换merge--commit 合并成功之后,执行commit操作-e, --edit commit之前编辑说明--ff 快进合并--ff-only 只执行快进合并,否则退出--rerere-autoupdate 尝试用之前的冲突解决方案来解决冲突--verify-signatures 执行GPG签名验证-s, --strategy 设置合并的策略-X, --strategy-option usage: git rebase [-i] [options] [--exec
] [--onto ] [ ] [ ]or: git rebase [-i] [options] [--exec ] [--onto ] --root [ ]or: git-rebase --continue | --abort | --skip | --edit-todoAvailable options are-v, --verbose 显示详细信息-q, --quiet 静默执行--autostash 自动加入stash中的内容--fork-point use 'merge-base --fork-point' to refine upstream--onto ... 变基到指定分支-p, --preserve-merges try to recreate merges instead of ignoring them-s, --strategy ... 使用指定的合并策略--no-ff cherry-pick all commits, even if unchanged-m, --merge 使用合并的方式来进行变基操作-i, --interactive 交互式执行-x, --exec ... 设置每一次commit之后的执行命令-k, --keep-empty 保存空的commit-f, --force-rebase 强制执行-X, --strategy-option ... 合并策略的选项--stat 显示受影响的内容-n, --no-stat 不显示受影响的内容--verify 允许pre-rebase钩子执行--rerere-autoupdate 尝试用之前的冲突解决方案来解决冲突--root rebase all reachable commits up to the root(s)--autosquash move commits that begin with squash move commits that begin with squash!/fixup! under -i--committer-date-is-author-date passed to 'git am'--ignore-date passed to 'git am'--whitespace ... passed to 'git apply'--ignore-whitespace passed to 'git apply'-C ... passed to 'git apply'-S, --gpg-sign[=...] GPG签名Actions:--continue continue--abort abort and check out the original branch--skip skip current patch and continue--edit-todo edit the todo list during an interactive rebase
rebase尽量在本地分支上执行,不要在公有分支上进行操作,若要执行rebase最好告知其它人员。
储藏区(stash)使用
储藏区一般在多分枝开发的情况下使用较多。例如,日常开发中,我们在featureA上进行开发,但是在开发中,临时需要解决bug。这时候如果我们在featureA上去解决bug,那么featureA的代码就乱了。若是想新建分支,则又需要将未完成的开发提前提交,这最终会导致自己的管理混乱。这时比较高效的解决办法就是使用储存区将featureA上的修改暂时存储,然后新建bug分支,在完成了bug的修复之后,再恢复储存区中保存的featureA中的修改内容。
- 保存
git stashgit stash save
- 恢复
git popgit apply
- 删除
git stash dropgit stash clear
- 查看
git stash listgit stash show
git中的存储区是以堆栈的形式来操作的,在日常开发中需要灵活使用。记得清理暂存区。
标签
Git中使用SHA-1值来标记每一次commit,可是这种方式缺少可读性。在版本演变的关键节点,可能需要记录相关信息,若是使用SHA-1值,则记录麻烦且缺乏可读性。这是就可以通过给commit打上tag的方式来解决这种问题。实际上Git中的tag仅仅是对commit的“指针”,但是可读性更高。
Git中的tag分为两类,一般式和标注式。其中标注式需要挟带操作人的签名信息,而一般式则不包含。# 在当前commit上,新建tag,v1.1git tag v1.1# 在45dfg8,commit上,新建tag,v1.1git tag v1.2 45dfg8# 在当前commit上,新建标注式tag, v1.3git tag -a v1.3 -m '这是1.3版本'
建议在代码版本演进的关键节点,打上相应标注式tag,以便于管理。
Git远程仓库和本地仓库互操作
- 克隆远程仓库代码
# 克隆demourl出的代码到demo目录git clone demourl demo
- 推送本地commit到远程仓库
# 推送到远程仓库的master分支git push origin master
origin是远程仓库的“简称”,可以设定为任意合法名称,并非只能为origin。
- 本地现有仓库关联远程仓库
# 本地master分支关联demourl的master分支git remote add origin demourl
- 本地分支关联远程仓库分支
# 本地dev分支关联远程仓库的dev分支git branch --set-upstream-to origin/dev# 取消本地分支和远程分支关联git branch --unset-upstream
- 推送本地标签到远程仓库
git push --tags origin master
- 拉取远程commit
git pull origin mastergit fetch origin master
pull和fetch的主要区别在于,pull是fetch和merge的合并。
usage: git push [] [ [ ...]] -v, --verbose 显示详细信息 -q, --quiet 静默执行 --repo 远程代码仓库 --all 推送所有引用 --mirror mirror all refs -d, --delete 删除远程分支 --tags 推送标签 -n, --dry-run 预演执行 --porcelain 机器可读的输出 -f, --force 强制更新 --force-with-lease[= : ] require old value of ref to be at this value --recurse-submodules[= ] control recursive pushing of submodules --thin use thin pack --receive-pack receive pack program --exec receive pack program -u, --set-upstream set upstream for git pull/status --progress 强制显示进度 --prune prune locally removed refs --no-verify bypass pre-push hook --follow-tags 推送丢失但是相关的标签 --signed[= ] GPG sign the push --atomic 远程仓库执行原子操作 -o, --push-option option to transmit -4, --ipv4 use IPv4 addresses only -6, --ipv6 use IPv6 addresses only
usage: git remote [-v | --verbose] or: git remote add [-t] [-m ] [-f] [--tags | --no-tags] [--mirror= ] or: git remote rename => 重命名远程仓库 or: git remote remove => 删除远程仓库 or: git remote set-head (-a | --auto | -d | --delete | ) => 设置远程仓库head引用 or: git remote [-v | --verbose] show [-n] => 显示远程仓库详细信息 or: git remote prune [-n | --dry-run] or: git remote [-v | --verbose] update [-p | --prune] [( | )...] or: git remote set-branches [--add] ... or: git remote get-url [--push] [--all] => 获取url地址 or: git remote set-url [--push] [ ] => 设置url地址 or: git remote set-url --add => 设置url地址, 添加新的url or: git remote set-url --delete => 设置url地址,删除url -v, --verbose 显示详细信息
最后更新日期:2017-09-07