Git 常用命令知识笔记
Git 仓库数据结构
- Git 仓库由一个个的
commit组成 - 某些
commit上会有一些branch指向它们,这些branch的本质是引用 - 有一个特殊的引用叫做
HEAD,它始终指向当前的位置,这个位置可以是commit,也可以是branch

staging area 暂存区和 add
staging原意:舞台表演前的筹划准备(例如汇集道具和演员)。Git 中的意思:把改动内容汇集起来以待提交。staging area:待提交的修改内容暂时存放的地方。主要用于和已经改动但不打算提交的内容区分开来。add指令:把指定的内容放进暂存区。

- Workspace:工作区
- Stage:暂存区
- Repository:仓库区(本地仓库)
- Remote:远程仓库
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
commit表示对于一次改动的提交,它可以代表当前时刻下 Git 仓库的完整快照,但本质上,commit只是记录了距离上一次commit之间的改动。
git commit -m [message] # 提交暂存区到仓库区
git commit [file1] [file2] ... -m [message] # 提交暂存区的指定文件到仓库区
git commit -a # 提交工作区所有更改到仓库区
git commit -v # 提交时显示所有diff信息
git commit -am 'message' # 将add和commit合为一步
# 使用一次新的commit,替代上一次提交
git commit --amend -m [message] # 如果代码没有任何新变化,则用来改写上一次commit的提交信息(用于反复修改)
git commit --amend [file1] [file2] ... # 重做上一次commit,并包括指定文件的新变化
branch 和 master
branch的含义是分支,指的是仓库结构出现分叉时的不同的「叉」- 本质上,git 的
branch是引用(reference),即指向某个commit的指针
直观感觉的 branch:

而实质上的 branch:

所以,branch 和你什么时候创建的它无关,也和仓库的起点无关,只和它当前指向哪个 commit 有关。
master是?个特殊的branch,因为它是 Git 的默认branch(默认branch可以修改)。默认branch的特点:- 执行
clone方法把仓库取到本地的时候,默认checkout出来的是默认branch,即master; - 执行
push命令把本地内容推送到远端仓库的时候,远端仓库的HEAD永远跟随默认branch,而不是和本地HEAD同步。换句话说,只有pushmaster分支到远端的时候,远端的HEAD才会移动。
- 执行
git branch # 列出所有本地分支
git branch -r # 列出所有远程分支
git branch -a # 列出所有本地分支和远程分支
git branch -v # 查看各个分支最后一次提交
git branch –merged # 查看哪些分支合并入当前分支
git branch –no-merged # 查看哪些分支未合并入当前分支
git branch [branch-name] # 新建一个分支,但依然停留在当前分支
git checkout -b [branch] # 新建一个分支,并切换到该分支
git branch [branch] [commit] # 新建一个分支,指向指定commit
git checkout - # 切换到上一个分支
git branch -d [branch-name] # 删除分支
git branch -D mybranch # 强制删除分支
git push origin --delete [branch-name] # 删除远程分支
git branch -dr [remote/branch] # 删除远程分支
HEAD
HEAD也是引用,但它不是branch,它代表了当前所处的位置。HEAD不仅可以指向某个commit,也可以指向某个branch(例如master、feature1)- 当每次
commit的时候,HEAD不仅随着新的commit一起移动,而且如果它指向了某个branch,那么它也会带着branch一起移动

git clone
clone是从远端仓库初次把数据取下来:
git clone https://github.com/xxxx.git
clone 命令具体会做两件事:
- 把整个仓库中的所有
branch取下来,并把从初始commit到达这些branch的路径上的所有commit都取下来:

- 从初始
commit开始,向master指向的commit,一个个地把每个commit应用,最终得到一个「当前」状态的仓库内容,写进 Git 所在的目录(这个目录叫做 working tree)
git log
- 从
HEAD指向的commit开始,倒序显示每一个commit的摘要信息(最新的排在最前面)
git status # 显示有变更的文件
git log # 显示当前分支的版本历史
git log --stat # 显示commit历史,以及每次commit发生变更的文件
git log -S [keyword] # 搜索提交历史,根据关键词
git log [tag] HEAD --pretty=format:%s # 显示某个commit之后的所有变动,每个commit占据一行
git log [tag] HEAD --grep feature # 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
git log --follow [file] # 显示某个文件的版本历史,包括文件改名
git whatchanged [file]
git log -p [file] # 显示指定文件相关的每一次diff
git log -5 --pretty --oneline # 显示过去5次提交
git shortlog -sn # 显示所有提交过的用户,按提交次数排序
git merge
merge就是合并,它会把当前commit和指定commit(所谓commit,可以直接用它的hash值来指定,例如4a0a1b,也可以用一个直接或间接指向它的引用来指定,例如master或者HEAD)进行合并,并把这个合并行为创建成一个新的commit。
git merge feature1 # 合并feature1分支至当前分支
git merge origin/master # 合并远程master分支至当前分支

git merge 会产生一个新的提交。
merge 行为所产生的 commit,是一种特殊的 commit:
- 它不需要有改动,只要指定两个(或更多个)父
commit就好 - 正如上面这句说的,它有两个或更多个父
commit,这是一般的commit不具有的性质
git checkout master 相当于merge from master,git merge mybranch 相当于 merge from mybranch。
merge 冲突
当 Git 不知道怎么合并某两处冲突的修改时,会中断自动合并,并对冲突文件进行标记。解决方法:
- 把文件手动修改好
- 把修改的内容使用
add来添加进暂存区 - 用
git merge --continue来继续自动合并流程
关于 origin/ 打头的 branch
- 本地仓库中,有一些以
origin/打头的branch,它们是远端仓库(别名为origin)的本地镜像。它们的作用是方便在本地查看远端仓库的branch状态。
远端仓库默认名称是
origin,但也可以给它们起别的名称
origin/ 分支并不在本地直接操作,它们一般只在两种情况下会进行自动更新:
- 在执行
push的时候,push成功后,push成功的branch会把它对应的origin/branch更新到当前commit(因为远端的branch已经随着push的成功而更新,所以本地镜像也一起更新) - 在执行
pull或者fetch的时候,由于从远端拿到了所有最新的branch状态,所以也会一同更新所有的origin/branch
关于
origin/HEAD:这是一个永远跟随origin/master的引用,它最大的作用是用来标记默认branch
git push
- 把当前的本地分支推送到远端仓库的指定分支。
git push origin feature1
具体做两件事:
- 把
HEAD所指向的branch(只是一个引用哦)推送到远端仓库 - 从这个
branch向前回溯,远端仓库缺少的每一个commit也推送到远端仓库。 - 将
push的branch的本地镜像origin/xxx更新




注意:
origin/HEAD并没有在图上画出来,但如果push是master(即默认branch),那么本地的origin/HEAD也会更新到master的最新位置;当push的是其他branch的时候,origin/HEAD并不会更新。
也就是说,origin/HEAD只和默认分支相关,和HEAD是无关的。
git push [remote] [branch] # 上传本地指定分支到远程仓库
git push [remote] --force # 强行推送当前分支到远程仓库,即使有冲突
git push [remote] --all # 推送所有分支到远程仓库
git push origin master # 将当前分支push到远程master分支
git pull
- 把远端
branch取到本地。
git pull origin feature1
具体做的事有三件:
- 把远端所有
branch的最新位置更新到本地的origin/xxx镜像 - 要到达这些
branch,本地所缺少的所有commit,也取到本地 - 把
origin/当前branch的内容合并到当前branch




事实上,git pull origin feature1 会分成两部执行,它等价于下面两行:
git fetch
git merge origin/feature1
git fetch 的含义:
git fetch [remote] # 下载所有远程分支,但不更新本地分支(另需merge)
git checkout
- 移动
HEAD,让它指向某个commit或某个branch。 checkout --detach:让HEAD脱离当前branch,直接指向下面的commit。
git checkout -b dev origin/master
从远程的 master 分支检出到本地的dev上,并切换到新建的本地dev分支上。
其实也是相当于两个命令的缩写:
git branch dev # 创建分支
git checkout dev # 切换分支
本地的项目中,一直都保留着一个master分支,并关联远程的master分支。本地的master分支,你可以当作是个干净的主线,每次新来一个需求的时候你都可以以该分支为基准,新建一个分支进行开发,最后进行合并,并由这个基准分支(本地master)提交到远程;具体的专业信息你可以参照文档:Git-分支-分支的新建与合并
通过 checkout 可以恢复指定文件(如不小心commit掉的)到工作区(未提交状态):
git checkout [file] # 恢复暂存区的指定文件到工作区
git checkout [commit] [file] # 恢复某个commit的指定文件到暂存区和工作区
git checkout . # 恢复暂存区的所有文件到工作区
git checkout -b master_copy # 从当前分支创建新分支master_copy并检出
git checkout -b master master_copy # 上面的完整版
git checkout features/performance # 检出已存在的features/performance分支
git checkout --track hotfixes/BJVEP933 # 检出远程分支hotfixes/BJVEP933并创建本地跟踪分支
git checkout v2.0 # 检出版本v2.0
git checkout -b devel origin/develop # 从远程分支develop创建新本地分支devel并检出
git checkout -- README # 检出head版本的README文件(可用于修改错误回退)
git rebase
- 把当前
commit(以及它之前的commits)应用到指定的需要rebase的commit上。
Git 中的每一个
commit都是不会改变的,所以rebase之后的每个commit都是新产生的,而不是对原先的commit进行「修改」

rebase 冲突
rebase 的冲突解决方法和 merge 冲突一样,只是把 git merge --continue 改成 git rebase --continue 就行了。
git reset
- 把当前
branch指向指定的commit。
git reset [指定commit] # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
移动到指定 commit,并保留 working tree 的内容。
git reset --hard [指定commit]
移动到指定 commit,并重置 working tree。
git checkout . # 撤销未暂存修改
git reset # 撤销未提交的暂存至 git add . 状态
git reset --hard # 撤销所有修改,保持与上一次一致
git reset --hard origin/master # 撤销本地提交
git reset --hard HEAD^ & git push –f # 撤销已推送
git reset --keep [commit] # 重置当前HEAD为指定commit,但保持暂存区和工作区不变
reset 和 checkout 的区别
它们都是移动 HEAD,但 chekcout 移动的时候是自己移动,不带着 branch 一起;而 reset 会带着 branch 一起移动。
git tag
git tag # 列出所有tag
git tag [tagname] # 新建一个tag在当前commit
git tag [tagname] [commit] # 新建一个tag在指定的commit
git tag -d [tagname] # 删除本地tag
另?种引用类型。作用:设置持久标记,例如版本号。和 branch 区别:
- 不能改变
- 不能被
HEAD指向 origin/master,origin/feature,origin/HEAD和tag有相似之处:也不能从本地改变位置,也不能被HEAD指向
git tag # 显示已存在的tag
git tag -a v2.0 -m 'xxx' # 增加v2.0的tag
git show v2.0 # 显示v2.0的日志及详细内容
git log v2.0 # 显示v2.0的日志
git checkout v2.0 # 检出版本v2.0
git checkout v2.0 会把远程 tag v2.0拉到本地,在本地创建一个无Head指向的分支,而远程tag分支不受任何影响,将本地分支push后将发布一个新的分支。
基于 tag 的 git check out 出来的分支可以执行 git branch xxx 创建新的本地分支,然后git check out xxx , commit后push到远端可以创建一个新分支(也可以不提交)。
git push [remote] [tag] # 提交指定tag
git push [remote] --tags # 提交所有tag
git checkout -b [branch] [tag] # 新建一个分支,指向某个tag
git push origin :refs/tags/[tagName] # 删除远程tag
git revert
- 撤销指定的提交,用于已经
push到master的内容需要删除。它的原理是创建一个新的commit,内容是指定commit的「相反内容」。
# 新建一个commit,用来撤销指定commit 后者的所有变化都将被前者抵消,并且应用到当前分支
git revert [commit]
git cherry-pick
- 选择指定的某个或某些
commit,合并进当前分支。 将commit到HEAD处。
git cherry-pick [commit1] [commit2]
git cherry-pick ff44785404a8e # 合并提交ff44785404a8e的修改
?如我想抛弃某个 branch,这个特性不要了,但它的某两个 commit 我希望保留。
git reflog
git reflog <branch>
查看指定的引用(HEAD 或 branch)的移动历史,从而找到之前的某个特定 commit
branch 的作用
- 让项目可以同时做多件事
- 未做完的事不会被项目真正收录

Feature Branching
- 做法:每开发一个新的功能做一个修复,都使用单独的分支,在做完之后
merge到master去 - 本地
merge:由于别人可能在你之前push过,所以你的push可能失败。所以通常会需要先pull一下,然后再push。

- 使用 github:先创建
pull request,在同事审阅完成之后,通过按钮实现在线merge pull request是什么:是开发者对远端仓库的提出的「拉取某个branch」的请求
Git Flow


两条持久主线:master 和 develop
master
- 最稳定的分支(长期分支),只用于存放所有的发布
- 每次有了新的
commit之后,立即打一个tag来记录 - 正式发布的集成目标
develop
- 日常开发分支(长期分支),用于存放不稳定版本的发布
develop并不是直接用于开发feature的,开发feature需要专门的branchdevelop在第一时间从master上分离出来- 需要开发任何功能的时候,从
develop创建出新的feature branch,开发完成后合并回develop(合并的时候使用--no-ff),然后删掉feature branch - 当下一正式版本需要的所有功能开发完成之后,从
develop上创建新的release branch,并在release branch合并到master后合并回develop(合并的时候用--no-ff),然后删掉release branch
feature branches
- 功能型开发分支(目的型分支)
- 始于
develop,终于develop,每次开发新功能是从develop创建,开发完成后合并到develop(使用--no-ff),然后被删掉
release branches
- 预交付分支(目的型分支)
- 始于
develop,终于master & develop - 每次下一版本的功能开发完毕后,从
develop上创建 - 创建完成后,更新版本号,然后单独做一个新的
commit - 如果有
bug fix,直接在release branch上修复,bug fix完成后,合并到master和develop(使用--no-ff),然后release branch被删掉
hotfix branches
- 热修复分支(目的型分支)
- 始于
master,终于master & develop - 已正式发布的产品发现
bug,直接从master或者出问题的tag上创建hotfix branch进行紧急修复,修复完成后合并到master和develop(或release branch如果有的话)(使用--no-ff),然后被删掉。
这里还有一个点,如果是本地创建的 feature 分支(从develop分支创建)开发完成后,成功合并到 develop 分支后,这个本地 feature 分支是可以删掉的,并不一定要提交到远程,不然远程仓库里会有很多冗余分支。
Git 配置
首先需要下载Git客户端:https://git-scm.com/
然后输入下面命令进行配置(主要是用户名信息):
# 设置提交代码时的用户信息
git config [--global] user.name "[name]" # 配置用户名
git config [--global] user.email "[email address]" # 配置邮件
git config --list # 显示当前的Git配置
git config -e [--global] # 编辑Git配置文件
Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)
生成 RSA 密钥 SSH Key
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub
第一次使用该命令时,之后会在用户目录下生成.ssh文件夹(如果是windows就是在C:/Users/用户名/目录下, 如果是Mac就用上面的cat命令查看即可),其中会包括:id_rsa、id_rsa.pub以及其他的文件,其中 id_rsa 是私钥,id_rsa.pub 是公钥。
将id_rsa.pub公钥文件中的内容全部复制,以使用 gitlab 仓库为例,打开gitlab,找到Profile Settings –> SSH Keys —> Add SSH Key,把复制的内容粘贴到Key所对应的文本框,在Title对应的文本框中给这个sshkey设置一个名字,点击Add key按钮。


检测是否配置成功:本地 git-bash 输入以下命令
$ ssh -T git@github.com
若显示如下,则代表配置成功:

绑定成功了之后,就可以复制 gitlab上面项目的 ssh 地址进行 git clone ,将 gitlab上项目克隆到本地了:

gitlab 上还可以添加项目成员和设置权限:

访问权限
- Private - 私有,只有属于该项目成员才能clone
- Internal - 内部,有Gitlab账号的人都可以clone
- Public - 公开,任何人可以clone
行为权限
- Guest - 访客
- Reporter - 报告者; 可以理理解为测试员、产品经理理等
- Developer - 开发者
- Master - 主人,负责对Master分?支进行维护
- Owner - 拥有者
git 克隆项目时使用 HTTPS url 跟 SSH url 的区别:
- 使用
https url克隆对初学者来说会比较方便,复制https url然后到git Bash里面直接用clone命令克隆到本地, 但是每次fetch和push代码都需要输入账号和密码,这也是https方式的麻烦之处。 - 而使用
SSH url克隆却需要在克隆之前先配置和添加好SSH key,因此,如果你想要使用SSH url克隆的话,你必须是这个项目的拥有者(或者你的项目的主管有权限添加SSH key)。否则你无法添加SSH key,另外 ssh 默认每次fetch和push代码不需要输入账号和密码,如果你想要每次都输入账号密码才能进行fetch和push也可以另外进行设置。
Git 命令速查表

这个图上的命令不全,这里有一个总结的比较全面的帖子:Git常用命令,总结的很全了!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!