Git
Git
本文基于https://liaoxuefeng.com/books/git/what-is-git/svn-vs-git/index.html
Git Cheat Sheethttps://liaoxuefeng.com/books/git/conclusion/git-cheat-sheet.pdf
创建版本库
git init
把这个目录变成Git可以管理的仓库git add file
添加文件到库git commit
命令,-m
后面输入的是本次提交的说明,可以输入任意内容。
时光机穿梭
git status
命令可以让我们时刻掌握仓库当前的状态git diff
顾名思义就是查看difference,显示的格式正是Unix通用的diff格式
提交新文件或者修改仍然使用git add file
版本回退
git log
命令显示从最近到最远的提交日志,加上--pretty=oneline
参数可以使输出更简化。
在Git中,用HEAD
表示当前版本,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写成HEAD~100
。git reset
:--hard
会回退到上个版本的已提交状态,而--soft
会回退到上个版本的未提交状态,--mixed
会回退到上个版本已添加但未提交的状态。
例如:git reset --hard HEAD^
如果要退回现在的版本,只要上面的命令行窗口还没有被关掉,找到HEAD版本的找到那个append GPL
的commit id
是什么,使用git reset --hard <commit id>
即可,版本号没必要写全,前几位就可以了。
如果已经关闭了命令行窗口,则要通过git reflog
(用来记录你的每一次命令)来查看当时的commit id。
工作区和暂存区
git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
管理修改
提交后,用git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别。
撤销修改
git checkout -- file
可以丢弃工作区的修改(git restore file
也可以)
这里有两种情况:
一种是readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。it reset HEAD <file>
可以把暂存区的修改撤销掉(unstage),重新放回工作区
删除文件
git rm
删掉,并且git commit
:从版本库中删除该文件
先手动删除文件,然后使用git rm <file>
和git add <file>
效果是一样的。
把误删的文件恢复到最新版本:git checkout -- file
远程仓库
添加远程库
远程库的名字就是origin
以后只要本地作了提交,就可以通过命令git push origin main
把本地main分支的最新修改推送至github。
从远程库克隆
git clone git@github.com:BlakeHansen130/repositoy-name.git
Git支持多种协议,包括https
,但ssh
协议速度最快。
分支管理
创建与合并分支
checkout
git checkout -b dev
:-b
表示创建并切换,相当于以下两条命令:
1 |
|
用git branch
命令查看当前分支:当前分支前面会标一个*
号。
把dev分支的工作成果合并到main上:git merge dev
用于合并指定分支到当前分支。git branch -d dev
删除dev分支。
switch
git switch -c dev
创建并切换到新的分支git switch main
切换到已有的分支
解决冲突
Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容git log --graph --pretty=oneline --abbrev-commit
可以看到分支的合并情况。
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
分支管理策略
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
Bug分支
git stash
:把当前工作现场“储藏”起来,等以后恢复现场后继续工作。git stash list
查看工作现场:
一是用git stash apply
恢复,但是恢复后,stash
内容并不删除,你需要用git stash drop
来删除;
另一种方式是用git stash pop
,恢复的同时把stash
内容也删了。
你可以多次stash
,恢复的时候,先用git stash list
查看,然后恢复指定的stash
,用命令:git stash apply stash@{0}
如何在另一分支上修改同样的bug?
git cherry-pick <bug-fixed commit id>
能复制一个特定的commit到当前分支
Feature分支
每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。git branch -D <name>
强行丢弃没有合并过的分支。
多人协作
git remote
查看远程库信息git remote -v
显示更详细的信息,上面显示了可以抓取和推送的origin
的地址。如果没有推送权限,就看不到push的地址。
从远程库clone时,默认情况下,只能看到本地的master
分支。
要在dev
分支上开发,就必须创建远程origin
的dev
分支到本地,用这个命令创建本地dev
分支:git checkout -b dev origin/dev
有冲突时,先用git pull
把最新的提交从origin/dev
抓下来,然后,在本地合并,解决冲突,再推送。
如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,即没有关联,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
rebase
- rebase操作可以把本地未push的分叉提交历史整理成直线;
- rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
git rebase
标签管理
创建标签
先切换到需要打标签的分支上,再git tag <name>
即可对最新的commit打标签。如果要对历史commit打标签,则git tag <name> <commit id>
。git tag
可以查看所有标签,标签不是按时间顺序列出,而是按字母排序的。git show <name>
可以查看标签信息。
还可以创建带有说明的标签,用-a
指定标签名,-m
指定说明文字:
例如:git tag -a v0.1 -m "version 0.1 released" 1094adb
标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
操作标签
git tag -d <name>
删除标签。创建的标签都只存储在本地,不会自动推送到远程。git push origin <name>
推送标签。一次性推送全部:git push origin --tags
如果标签已经推送到远程,先从本地删除git tag -d <name>
,再从远程删除git push origin :refs/tags/<name>
。
使用GitHub
点“Fork”就在自己的账号下克隆了一个仓库,然后,从自己的账号下clone,这样才能推送修改。如果你希望官方库能接受你的修改,你就可以在GitHub上发起一个pull request。
自定义Git
忽略特殊文件
在Git工作区的根目录下创建一个特殊的.gitignore
文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
检验.gitignore
的标准是git status
命令是不是说working directory clean
。
如果想强制添加.ignore文件中的文件到Git,那么git add -f file
;也可以用git check-ignore
来检查哪行规则忽略了该文件。
把指定文件排除在.gitignore
规则外的写法就是!
+文件名,所以,只需把例外文件添加进去即可。
在线生成.gitignore
文件并直接下载:https://michaelliao.github.io/gitignore-online-generator/
一个Git仓库也可以有多个.gitignore
文件,.gitignore
文件放在哪个目录下,就对哪个目录(包括子目录)起作用。
配置别名
配置Git的时候,加上--global
是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。每个仓库的Git配置文件都放在.git/config
文件中,当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中。