git使用指南
09 Feb 2020 - Sindweller-ch
git指南
本文基于个人git使用经验总结而成,可供初学者上手参考,欢迎补充与指正! 下载安装config以及添加ssh等请自行搜索完成。
git仓库
本地 | fork | 上游 |
---|---|---|
local | origin | upstream |
基于本地仓库修改代码 | 自己fork的仓库,拥有修改权限,可以push本地代码 | 源仓库,一般没有修改权限,所以无法直接push;拥有最新版本的代码 |
本地仓库初始化相关命令
需求分析:
我要开始为开源社区做贡献了!
git初始化命令
新建本地目录,在该目录下进行如下操作:
已有项目远程仓库
- 下载代码
git clone origin_ssh_url
- 添加与之关联的上游仓库(名字可以随意,建议命名为upstream)
git remote add upstream upstream_ssh_url
ok,到这里就把github里的项目挪到本地了,下一步是开发前的准备——更新/新建分支。
本地项目尚未上传
- 初始化本地git仓库
git init
- 添加与之关联的fork仓库(名字可以随意,建议命名为origin)
git remote add origin origin_ssh_url
- 确认关联仓库
git remote -v
更新本地代码
需求分析:
- upstream仓库有更新,而自己fork的origin仓库和本地代码不会自动与之同步。
- 其他原因导致本地代码落后于upstream(或origin,极特殊情况)的代码
实际上,origin/master是不需要单独更新的,因为只要将local/master更新至upstream/master,就可以在本地master的基础上新建本地分支,基于最新代码进行修改。修改完成后再push至origin上。
git更新本地代码命令
- 拉取上游代码
git fetch upstream
- 同步本地分支 local/master -> upstream/master
git rebase upstream/master
- 此时使用
git status
查看状态
会发现本地代码已经同步了上游的代码,领先了origin的代码,此时已经可以开始开发了。如果你非要让origin也同步:git push origin master
接下来就可以进行开发了~
分支
需求分析:
- 需要开发多个独立的功能,并以pr的方式逐一提交。
- 需要保留master上的代码。
注:
分支同样分为本地(local)分支、origin分支、upstream分支。
一般在本地,与上游代码同步后,基于local/master新建本地分支,该分支中的代码继承master,且在该分支上的改动不会影响local/master中的代码。
建议开发时,尽量将不同分支上开发无互相依赖的不同功能,如在branch A上开发A功能,切换到branch B上开发B功能……
分支之间互不影响,但仍然要注意是否有依赖,否则会在合并时出现冲突。尽量使各功能的开发独立。
开发新功能时请记得切换回到master再新建分支!!
git分支常用命令
git checkout branch_name
切换至branch_name分支
git checkout -b new_branch
新建并切换至new_branch分支
git branch -a
查看所有分支(标记的为所在分支)
git branch -D branch_name
删除本地的branch_name分支(请不要直接在该分支上做这种过河拆桥的事情),该操作不会影响远程仓库的分支
git push origin :branch_name
或git push origin --delete branch_name
删除远程分支——fork仓库的branch_name分支
提交本地代码
需求分析:
- 保存,防止电脑突然歇菜
- 暂存,以便之后放弃修改回退到该状态
- 开发完成,准备回馈上游社区
git提交命令
本地代码的提交分为三步:推到暂存区、添加提交内容描述、推到origin仓库的新分支上
- 建议先确认下修改内容,是不是在正确的分支上,因为如果搞错了,这里没有新修改的内容,是推不上去的
git status
- 将本地修改推到暂存区
git add -A
(-A
的意思是全部)有许多网上教程在这一步写的是
git add .
,但该命令仅提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件;git add -u
表示将已跟踪文件中的修改和删除的文件添加到暂存区,不包括新增加的文件;-A
则包括以上两种功能
git add -i
可以查看所有被所有修改过或已删除文件但没有提交的文件
git add [<path>]
可以指定添加文件或目录至暂存区 - 添加提交描述,这个commit会显示在仓库首页,即最近一次修改,请用简洁正常语句撰写,之前的所有commit也都会保留在github的仓库里,这样比较好看版本修改内容
git commit -m "simple normal words"
- 推送至origin仓库新分支,建议跟本地分支同名
git push origin new_branch
然后就可以打开github网页,自己的仓库首页就会提醒你是否根据这个branch创建pr。
合并多个提交commit
需求分析:
在修改代码的过程中,我们在本地与origin仓库间可能存在着多次提交(commit),建议最终提交pr时,合并所有commit,保证该pr内仅包含一次提交。
尽管可以经由审查人员直接在merge时合并所有提交,但仍期望在pr中有着干净的提交记录,规范的pr可以反映出提交者的专业性。
以下命令同样适用于在已提交pr的情况下继续修改该分支代码,pr会自动与分支代码同步,通过使用git commit --amend
和git push --force
强制推送来保证只有一次commit记录
git合并多个提交命令
- 查看log
git log
这里会出现很多个commit,找到你需要合并的commit,比如将最新一个(HEAD所指)commit和第二个合并为一次提交,复制作为父亲的提交后面那一串 c47e54a3c35b6cec9f5fd2be0fc3905785df6df0之类的 - 重置提交状态到父提交时,之后会在这个基础上提交一次新的、合并了所有需要合并的提交的提交
git reset xxxxx
- 重新推到暂存区
git add -A
- 对提交内容描述进行修改
git commit --amend
会进入文本编辑,修改描述,之后的commit就只有这次描述了,合并的commit里的旧描述可以注释掉
- push到origin
git push -f origin xxx
-f
的作用是强制推送到orign,因为前面在本地合并commit之后,对应的远程分支中的commit并没有变化,git会认为远程分支的提交领先于本地分支
强制推送之后即可合并远程分支上的commit
刷新github看看commit记录
代码版本回退、合并
需求分析:
- 开发进行中,远程代码已更新,需要同步
- 放弃本地修改
git同步与合并命令
- 先拉取upstream
git fetch upstream
- 需要版本回退,用upstream/master更新本地代码
git rebase upstream/master
- 或者需要合并本地代码和上游代码
git merge upstream/master
可能会遇到各种冲突,根据git提示来就行,直接打开vscode也会给你标出冲突的地方,选择就行git rebase
比git merge
要好,想要更好的提交树,使用rebase
操作会更好一点。这样可以线性的看到每一次提交,并且没有增加提交节点。
merge
操作遇到冲突的时候,当前merge
就不能继续进行了。手动修改冲突内容后,add
提交修改,再commit
就可以了。
而rebase
操作的话,会中断rebase
,同时会提示去解决冲突。解决冲突后,将修改add
后执行git rebase –continue
继续操作,或者git rebase –skip
忽略冲突。
放弃本地修改
这里分三种修改阶段:
- 本地修改还没有使用
git add
命令提交至暂存区,使用:
git checkout -- filepathname
如果需要放弃所有的文件修改,可以使用git checkout .
- 本地修改已经由
git add
缓存:
git reset HEAD filepathname
重置,放弃指定文件的缓存,同样如果需要放弃所有缓存可以使用git reset HEAD .
命令 此时本地修改还未完全消失,而是回到1.的状态,后续操作同上 - 已经用
git commit
提交了代码:
git reset --hard HEAD^
回退至上一次commit的状态
git reset --hard commitid
回退至任意commit状态(使用git log
来查看git的commit历史,确定需要的commitID)
本地新建文件并没有加入到git的管理系统中,对于git来说是未知的(untracked files),如果放弃该文件,需要手动删除或使用:
git clean -fd -n
查看确认需要删除的文件
git clean -fd
即可删除,其中-f
表示文件-d
表示目录。如果需要删除.gitignore
中的文件,再加上-x
;如果git submodule
中也有需要删除的文件,加上-f
变成git clean -dff
。
简单来说,删除git未跟踪文件可以这样执行:git clean -f
需要注意,在开发过程中,本地有可能自动生成.classpath
等编译文件,这些在提交之前都需要用git clean -f
清除
修改pr
直接修改对应的本地分支再git push --force origin xxx
到origin对应分支就行了,pr会自动跟着branch的commit变
总结
综上,一套完整的开发、提交pr流程一般为:
- 新建本地目录,后续操作都需要在这个目录下进行
- 第一种情况:
如果不存在远程仓库,即为还未上传的本地项目,在该目录下,git init
初始化本地git仓库,这个命令用一次就行了,之后基于该仓库的操作请勿再使用init命令,人生没有重来,本地仓库也是
git remote add origin ssh_url
ssh_url是复制自己的仓库的ssh,将本地仓库关联该远程仓库
git remote -v
查看关联的仓库
第二种情况:
Github上已有项目远程仓库
git clone ssh_url
将代码下载下来,建议使用fork的origin仓库
git remote add upstream ssh_url
关联上游仓库
git remote -v
查看关联的仓库
git fetch upstream
+git rebase upstream/master
开发之前一定要确保本地代码与上游同步,是最新的 git checkout -b feature-A
基于local/master,新建本地分支,开发功能A- 开发ing……
- 开发完成后,
git status
看看修改的文件是不是那几个,确认后git add -A
把所有的文件(代码)加入暂存区(或者git add [<path>]
将指定文件或目录加入暂存区) git commit -m "the changes"
添加一次提交,”“内填写本次提交概述git push origin branch_name
将刚才加入暂存区的文件(代码)和提交内容推到origin的branch_name分支中- 在github网页上,将origin/branch_name分支以pr形式提交给上游仓库
- 如若需要进行下一个功能的开发,记得切换回master分支,再新建本地feature-B分支进行B功能的开发
注意!
为国争光,禁用pull,从我做起。
git pull
是一个非常强硬的命令,它会忽略一切细节并且可以把git fetch
、git merge
和git rebase
等等的活儿都干了,中间没有出于安全考虑的确认
该命令还会将合并结果记录在新提交中,包含两个父提交的名称以及来自用户的描述更改的日志消息
虽然简单,但请勿使用git pull