git reset
1.使用git add .添加了所有修改文件到暂存区之后在commite到本地之前想撤销add操作可以使用1
git reset HEAD <file>
将某个文件从暂存区拿出来。
2.已经commite了提交到了本地但是还没有push到远端,这时候发现有个文件不能提交到远端可以使用1
git reset -soft/--mix/--hard <commite id>
会将本地仓库回退到commite id这个版本(可以是上一次commite的版本)。reset后的参数代表了是否保留本地代码的修改,具体可以查询网络。git reset命令的使用
选项 | git reset的影响 | ||
---|---|---|---|
选项 | HEAD | 索引(暂存区) | 工作目录(源代码) |
–soft | 是 | 否 | 否 |
–mix | 是 | 是 | 否 |
–hard | 是 | 是 | 是 |
HEAD:表示当前git指针指向的位置
索引:表示add之后去到的暂存区
工作目录:表示代码文件的改动
提交C1 –> 提交C2
总结就是:soft后git指针会指向C1的提交,而C2修改的文件还是add状态,修改内容不会丢失,对现有的版本改动最小;mix后(git reset默认操作)git指针会指向C1提交,C2修改的文件不是add状态(需要重新add)不在暂存区,文件修改内容不丢失;hard后git指针指向C1提交,C2修改文件不在暂存区,文件修改丢失,完全恢复到C1提交的状态.hard慎用
或者
一行一行源码分析清楚+AbstractQueuedSynchronizer+-二-1
2git reset HEAD~
git reset HEAD~1
如果你提交了多个commit,那么可以通过修改HEAD~之后的数字,如撤销前3次的commit
1 | git reset HEAD~3 |
下面是一个很有用的后悔药
1
2# 查询所有git的提交记录,包括详细commite id
git reflog
下图为git reflog的界面
这里面记录了你本地仓库中相关切换和更改的详细描述清单,你可以通过:
1 | # 可以通过以下命令回到任何一个位置 |
git add语法
语法 | 描述 |
---|---|
git add -A | stages All |
git add . | stages new and modified, without deleted |
git add -u | stages modified and deleted, without new |
git merge合并
现在最简单的merge模式就是fast-farward merge了,就是从master拉出的分支develop后,master没有再做任何修改,所有的代码都在develop分支上提交,等到最后要合并develop到master上时,可以使用如下命令:
1 | # 切换到Master分支 |
git tag打标签
标签可以针对某一时间点的版本做标记,常用于版本发布。
1.列出标签
1 | # 在控制台打印出当前仓库的所有标签 |
2.打标签
git标签分为两种类型:轻量标签和附注标签。轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象。建议使用附注标签。
1 | # 创建轻量标签 |
3.切换标签
1 | git show v0.1.2 |
4.删除标签
1 | # 删除本地标签 |
5.标签发布
通常的git push不会将标签对象提交到git服务器,我们需要进行显式的操作:
1 | # 将v0.1.2标签提交到git服务器 |
git stash
该命令用来保存当前分支上还没commite的修改,使当前分支保持clean状态(git status)
使用场景:
执行git stash后,你在dev分支没有提交的修改暂时被“藏”了起来,看起来dev分支是干净的。但是,请一定注意,你还在dev分支!因为你需要切换到master分支去修改bug,因此此时需要切换到master分支(如果不执行git stash就切换到master分支是不行的:git会报告当前dev分支还存在未提交的修改,比如先提交才允许你切换分支,而出于各种原因,你还不能现在提交dev分支的内容(一般也就先提交了,大不了再切回来改就是哦),这就是git stash存在的价值)。
切换到stash分支后的恢复命令1
2
3
4
5
6
7
8# 恢复并删除stash内容
git stash pop
# 查看现场
git stash list
# 保存现场
git stash
git分支管理
master
:主分支,当前分支上的代码随时可以直接发布,并且只能通过Pull Request从其他分支进行合并,而不能直接push修改。当开发告一段落,产生了新的可供发布的代码时,master分支通过Pull Request更新了代码,同时,每一次更新必须添加对应版本号的标签TAG。develop
:开发分支,保存当前最新开发成果的分支,即当一个新功能开发完毕需要先合并到develop分支,这个分支的代码会进行每日的代码持续集成(Daily Build)。所有的开发任务都是从这个分支Checkout新的特性分支进行开发。feature
:特性分支,当开发新的功能时,从develop分支Checkout新的feature分支,这个分支的代码最终要合并回develop分支或者废弃掉(例如预研功能效果不好时)。feature分支最好以功能为单位。hotfix
:紧急修复分支,唯一从master分支派生的分支,当生产环境中发现了异常或者缺陷的时候,从master分支上指定的TAG版本Checkout hotfix分支进行紧急修复工作,当修复完成之后,必须同时合并到master分支和develop分支。合并完代码之后删除hotfix分支。新建分支(已feature为例)
1
2
3
4
5
6
7
8# 切换本地分支到develop分支
git checkout develop
# 拉取远程Git仓库中的最新的develop分支的代码
git pull
# 创建本地特性分支feature
git checkout -b feature
# 推送本地特性分支到远程Git仓库(即创建远程特性分支),-u为追踪远程分支
git push -u origin feature已feature分支为例开发合并全流程
1
2
3
4
5# 开发代码。以下两步的作用是保证你本地的feature分支的代码为最新,因为有可能你是和别人合作开发的该功能,如果你刚更新过或者你是一个人在开发则可以省略此操作
# 切换到本地feature分支
git checkout feature
# 拉取远程分支代码,--rebase最好加上
git pull --rebase
1 | # 合并代码 |
1 | # 代码已经合并完,可以删除本地特性分支和远程特性分支 |
当你用上面删除远程分支(删除tag)命令时,当你的分支名称和tag名称一样时,会报错,因为git不知道你到底要删除branch还是head。所以可以这样做
1 | //删除 dev_test 分支 |
- 本地根据tag创建分支
1 | # 根据tag创建分支 |
git push
push到远程分支有https和ssh两种方式,https每次push都会要求输入用户名和密码,而ssh只要在远端注册了ssh key则不需要。
另外,ssh可以上传大文件,https貌似不行。1
2# 这个会把本地当前分支的内容push到远端的demo分支,如果远端没有该分支则自动创建
git push -u origin demo
1 | # 生成ssh key,该程序在 Linux/Mac 系统上由 SSH 包提供,而在 Windows 上则包含在 MSysGit 包里: |
git reset
第一小节有类似操作。
- 本地代码回滚
1 | # 回滚到commit-id,讲commit-id之后提交的commit都去除 |
- 远程代码回滚。应用场景:app已经发布了,发现有问题需要回滚到某个commit,再重新发布。这时需要先将本地分支退回到某个commit,删除远程分支,再重新push本地分支。操作步骤(还没检验)
1 | # 1 |
git remote
多源操作,一般是一个源,但是多源也很有用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 如果想关联另一个远端仓库(加一个源)
git remote add <origin name> git@gitlab.com:demo/demo.git
# 显示全部源
git remote / git remote -v
# rename
git remote rename <origin name> <origin new name>
# deleted
git remote rm <origin name>
# 查看指定源的全部信息
git remote show <origin name>
# 修改远程仓库地址
git remote set-url origin <origin url>
git commit
合并某个分支上的某个commit或者多个commit到master分支上1
2
3dd2e86 - 946992 -9143a9 - a6fd86 - 5a6057 [master]
\
76cada - 62ecb3 - b886a0 [feature]
- 比如,feature 分支上的commit 62ecb3 非常重要,它含有一个bug的修改,或其他人想访问的内容。无论什么原因,你现在只需要将62ecb3 合并到master,而不合并feature上的其他commits,所以我们用git cherry-pick命令来做:
1 | # 示例 |
- 在一些特性情况下,合并单个commit并不够,你需要合并一系列相连的commits。这种情况下就不要选择cherry-pick了,rebase 更适合。还以上例为例,假设你需要合并feature分支的commit76cada ~62ecb3 到master分支。(未实验,要实验一下)
1 | # 首先需要基于feature创建一个新的分支,并指明新分支的最后一个commit: |
git rebase
1 | ``` |
HEAD指向了一个未知的分支,可用git checkout -b基于当前分支创建一个新的临时分支保留代码,合并到合适的分支后删除1
2
3
4
5
6
7
8
9
10
11
12
13$ git checkout -b temp
Switched to a new branch 'temp'
$ git branch
dev
master
* temp
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git merge temp
Already up-to-date.
$ git branch -d temp
Deleted branch temp (was 3e74a7a).
git clean -d -fx “{文件名}”
在开发中碰到本地修改了一个文件,远程分支对应文件也有修改。后面忘记先pull代码直接commit了,然后想push到远端仓库,发现会报一个错误如下:
git冲突please move or remove before you can merge
解决方法就是:
1 | //默认会把这个文件强制更新为远程文件 |
git diff
该命令用来比较分支和分支之间的差异
显示两个分支的差异部分
1
git diff branch1 branch2 --start
显示指定文件的详细差异
1
git diff branch1 branch2 具体文件路径
显示出所有有差异的文件的详细差异
1
git diff branch1 branch2
git log
显示git日志的,有时候非常有用
查看branch1分支有,而branch2分支中没有的log
1
git log branch1 ^branch2
查看branch2中比branch1中多提交了哪些内容
1
git log branch1..branch2
不知道谁提交的多谁提交的少,单纯想知道有什么不一样
1
git log branch1...branch2
在上述情况下,在显示出每个提交是在哪个分支上
1
2// 打印出的commit中根据命令中left-right,左箭头<表示branch1的,右箭头>表示branch2的
git log -left-right branch1...branch2