git 快速入门
git 是什么?
git 是一个 分布式 、最流行、最先进、2005由 linux torvalds 开发的版本管理系统 。
github、gitlab、Bitbucket 是什么?
GitHub是一个面向开源及私有软件项目的托管平台,因为只支持git作为唯一的版本库格式进行托管,故名GitHub。2008年4月10日正式上线,2018年6月4日,微软买了。
GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务。GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务
Git基础
Git是一个分布式版本控制系统,保存的是文件的完整快照,而不是差异变化或者文件补丁。
保存每一次变化文件的完整内容
Git 每一次提交都是对项目文件的一个完整拷贝,因此你可以完全恢复到以前的任一个提交而不会发生任何区别。这里有一个问题:如果我的项目大小是10M,那 Git占用的空间是不是随着提交次数的增加线性增加呢?我提交(commit)了10次,占用空间是不是100M呢?很显然不是,Git是很智能的,如果 文件没有变化,它只会保存一个指向上一个版本的文件的指针,即,对于一个特定版本的文件,Git只会保存一个副本,但可以有多个指向该文件的指针。
未变化的文件只保存上一个版本的指针
Git工程有三个工作区域:工作目录,暂存区域,以及本地仓库。工作目录是你当前进行工作的区域;暂存区域是你运行git add命令后文件保存的区域,也是下次提交将要保存的文件(注意:Git 提交实际读取的是暂存区域的内容,而与工作区域的文件无关,这也是当你修改了文件之后,如果没有添加git add到暂存区域,并不会保存到版本库的原因);本地仓库就是版本库,记录了你工程某次提交的完整状态和内容,这意味着你的数据永远不会丢失。
相应的,文件也有三种状态:已提交(committed),已修改(modified)和已暂存(staged)。已提交表示该文件已经被安全地保存在本 地版本库中了;已修改表示修改了某个文件,但还没有提交保存;已暂存表示把已修改的文件放在下次提交时要保存的清单中,即暂存区域。所以使用Git的基本 工作流程就是:
- 在工作区域增加,删除或者修改文件。
- 运行git add,将文件快照保存到暂存区域。
- 提交更新,将文件永久版保存到版本库中。
git 常用命令:
我每天使用 Git ,但是很多命令记不住。
一般来说,日常使用只要记住下图6个命令,就可以了。但是熟练使用,恐怕要记住60~100个命令。
下面是我整理的常用 Git 命令清单。几个专用名词的译名如下。
- Workspace:工作区
- Index / Stage:暂存区
- Repository:仓库区(或本地仓库)
- Remote:远程仓库
一、新建代码库
# 在当前目录新建一个Git代码库 $ git init # 新建一个目录,将其初始化为Git代码库 $ git init [project-name] # 下载一个项目和它的整个代码历史 $ git clone [url]
二、配置
Git的设置文件为.gitconfig
,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。
# 显示当前的Git配置 $ git config --list # 编辑Git配置文件 $ git config -e [--global] # 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]"
三、增加/删除文件
# 添加指定文件到暂存区 $ git add [file1] [file2] ... # 添加指定目录到暂存区,包括子目录 $ git add [dir] # 添加当前目录的所有文件到暂存区 $ git add . # 添加每个变化前,都会要求确认 # 对于同一个文件的多处变化,可以实现分次提交 $ git add -p # 删除工作区文件,并且将这次删除放入暂存区 $ git rm [file1] [file2] ... # 停止追踪指定文件,但该文件会保留在工作区 $ git rm --cached [file] # 改名文件,并且将这个改名放入暂存区 $ git mv [file-original] [file-renamed]
四、代码提交
# 提交暂存区到仓库区 $ git commit -m [message] # 提交暂存区的指定文件到仓库区 $ git commit [file1] [file2] ... -m [message] # 提交工作区自上次commit之后的变化,直接到仓库区 $ git commit -a # 提交时显示所有diff信息 $ git commit -v # 使用一次新的commit,替代上一次提交 # 如果代码没有任何新变化,则用来改写上一次commit的提交信息 $ git commit --amend -m [message] # 重做上一次commit,并包括指定文件的新变化 $ git commit --amend [file1] [file2] ...
五、分支
# 列出所有本地分支 $ git branch # 列出所有远程分支 $ git branch -r # 列出所有本地分支和远程分支 $ git branch -a # 新建一个分支,但依然停留在当前分支 $ git branch [branch-name] # 新建一个分支,并切换到该分支 $ git checkout -b [branch] # 新建一个分支,指向指定commit $ git branch [branch] [commit] # 新建一个分支,与指定的远程分支建立追踪关系 $ git branch --track [branch] [remote-branch] # 切换到指定分支,并更新工作区 $ git checkout [branch-name] # 切换到上一个分支 $ git checkout - # 建立追踪关系,在现有分支与指定的远程分支之间 $ git branch --set-upstream [branch] [remote-branch] # 合并指定分支到当前分支 $ git merge [branch] # 选择一个commit,合并进当前分支 $ git cherry-pick [commit] # 删除分支 $ git branch -d [branch-name] # 删除远程分支 $ git push origin --delete [branch-name] $ git branch -dr [remote/branch]
六、标签
# 列出所有tag $ git tag # 新建一个tag在当前commit $ git tag [tag] # 新建一个tag在指定commit $ git tag [tag] [commit] # 删除本地tag $ git tag -d [tag] # 删除远程tag $ git push origin :refs/tags/[tagName] # 查看tag信息 $ git show [tag] # 提交指定tag $ git push [remote] [tag] # 提交所有tag $ git push [remote] --tags # 新建一个分支,指向某个tag $ git checkout -b [branch] [tag]
七、查看信息
# 显示有变更的文件 $ git status # 显示当前分支的版本历史 $ git log # 显示commit历史,以及每次commit发生变更的文件 $ git log --stat # 搜索提交历史,根据关键词 $ git log -S [keyword] # 显示某个commit之后的所有变动,每个commit占据一行 $ git log [tag] HEAD --pretty=format:%s # 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件 $ git log [tag] HEAD --grep feature # 显示某个文件的版本历史,包括文件改名 $ git log --follow [file] $ git whatchanged [file] # 显示指定文件相关的每一次diff $ git log -p [file] # 显示过去5次提交 $ git log -5 --pretty --oneline # 显示所有提交过的用户,按提交次数排序 $ git shortlog -sn # 显示指定文件是什么人在什么时间修改过 $ git blame [file] # 显示暂存区和工作区的差异 $ git diff # 显示暂存区和上一个commit的差异 $ git diff --cached [file] # 显示工作区与当前分支最新commit之间的差异 $ git diff HEAD # 显示两次提交之间的差异 $ git diff [first-branch]...[second-branch] # 显示今天你写了多少行代码 $ git diff --shortstat "@{0 day ago}" # 显示某次提交的元数据和内容变化 $ git show [commit] # 显示某次提交发生变化的文件 $ git show --name-only [commit] # 显示某次提交时,某个文件的内容 $ git show [commit]:[filename] # 显示当前分支的最近几次提交 $ git reflog
八、远程同步
# 下载远程仓库的所有变动 $ git fetch [remote] # 显示所有远程仓库 $ git remote -v # 显示某个远程仓库的信息 $ git remote show [remote] # 增加一个新的远程仓库,并命名 $ git remote add [shortname] [url] # 取回远程仓库的变化,并与本地分支合并 $ git pull [remote] [branch] # 上传本地指定分支到远程仓库 $ git push [remote] [branch] # 强行推送当前分支到远程仓库,即使有冲突 $ git push [remote] --force # 推送所有分支到远程仓库 $ git push [remote] --all
九、撤销
# 恢复暂存区的指定文件到工作区 $ git checkout [file] # 恢复某个commit的指定文件到暂存区和工作区 $ git checkout [commit] [file] # 恢复暂存区的所有文件到工作区 $ git checkout . # 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变 $ git reset [file] # 重置暂存区与工作区,与上一次commit保持一致 $ git reset --hard # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变 $ git reset [commit] # 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致 $ git reset --hard [commit] # 重置当前HEAD为指定commit,但保持暂存区和工作区不变 $ git reset --keep [commit] # 新建一个commit,用来撤销指定commit # 后者的所有变化都将被前者抵消,并且应用到当前分支 $ git revert [commit] # 暂时将未提交的变化移除,稍后再移入 $ git stash $ git stash pop
十、其他
# 生成一个可供发布的压缩包 $ git archive
GitLab工作流遵循以下11条原则:
-
使用功能分支进行开发,而不是直接在
master
分支上提交代码 (如果你的开发主分支是master
的话,下同) -
测试每一次commit,而不仅仅是对
master
分支进行测试 -
在所有commits上运行自动化测试(如果你的测试脚本运行时间超过5分钟,就让他们并行)
-
在合并代码之前进行code review,而不是在合并之后
-
以分支名或者tag为准进行自动化的部署
-
tag由人来设定,而不是CI
-
发布版本应建立在tag上
-
已push的commits永远不要进行rebase
-
所有人从
master
派生新分支,最终合并回`master -
修复bug时应该优先修复
master
分支的代码,修复之后再cherry-pick到线上分支 -
commit messages 要有意义
github flow
https://docs.github.com/en/get-started/quickstart/github-flow
3. 带有 Develop 分支的 Git 功能分支工作流
此工作流是开发团队中比较流行的工作流之一。它与 Git 功能分支工作流相似,但它的 develop 分支与 master 分支并行存在。
在此工作流中,master 分支始终代表生产环境的状态。每当团队想要部署代码到生产环境时,他们都会部署 master 分支。
Develop 分支代表针对下一版本的最新交付的代码。开发人员从 develop 分支创建新分支,并开发新功能。功能开发完毕后,将对其进行测试,与 develop 分支合并,在合并了其他功能分支的情况下使用 develop 分支的代码进行测试,然后与 master 分支合并。
上图为具有 develop 分支的 Git 功能分支工作流模型。
此工作流的优点是,它使团队能够一致地合并所有新功能,在预发布阶段对其进行测试并部署到生产环境中。尽管这种工作流让代码维护变得更加容易,但是对于某些团队来说,这样做可能会感到有些疲倦,因为频繁的 Git 操作可能会让你感到乏味。
4. Gitflow 工作流
Gitflow 工作流与我们之前讨论的工作流非常相似,我们将它们与其他两个分支( release 分支和 hot-fix 分支)结合使用。
4.1 Hot-Fix 分支
Hot-fix 分支是唯一一个从 master 分支创建的分支,并且直接合并到 master 分支而不是 develop 分支。仅在必须快速修复生产环境问题时使用。该分支的一个优点是,它使你可以快速修复并部署生产环境的问题,而无需中断其他人的工作流,也不必等待下一个发布周期。
将修复合并到 master 分支并进行部署后,应将其合并到 develop 和当前的 release 分支中。这样做是为了确保任何从 develop 分支创建新功能分支的人都具有最新代码。
4.2 Release 分支
在将所有准备发布的功能的代码成功合并到 develop 分支之后,就可以从 develop 分支创建 release 分支了。
Release 分支不包含新功能相关的代码。仅将与发布相关的代码添加到 release 分支。例如,与此版本相关的文档,错误修复和其他关联任务才能添加到此分支。
一旦将此分支与 master 分支合并并部署到生产环境后,它也将被合并回 develop 分支中,以便之后从 develop 分支创建新功能分支时,新的分支能够具有最新代码。
上图为具有 hot-fix 和 release 分支的 Gitflow 工作流模型
此工作流由 Vincent Driessen 首次发布并广受欢迎,已被具有预定发布周期的组织广泛使用。
由于 git-flow 是对 Git 的包装,因此你可以为当前代码库安装 git-flow。git-flow 非常简单,除了为你创建分支外,它不会更改代码库中的任何内容。
要在 Mac 机器上安装 ,请在终端中执行 brew install git-flow
。
要在 Windows 机器上安装,你需要 下载并安装 git-flow 。安装完成后,运行 git flow init
命令,就可以在项目中使用它了。
original 的解释: https://www.zhihu.com/question/27712995