learn git~ # 初始化一个仓库 git init # 添加文件 git add readme.txt # 提交文件 git commit -m "add a readme.txt" now change readme.txt # 查看仓库当前的状态 git status # 查看修改的地方 git diff readme.txt # 修改需要提交, 继续git add, git commit # 版本回退 # HEAD指向当前版本, ^, ~<num> # 本地 版本回退, 回到过去 git reset --hard commit_id # 查看提交历史 git log # 查看命令历史, 确定要移动到的版本,回到未来 git reflog # git 工作区与暂存区 在进行add时, 是将修改的文件存放在暂存区 commit提交暂存区的内容 # git跟踪管理的是修改,而非文件 # 撤销修改(工作区),将readme.txt文件在工作区的修改撤销,回到最近一次git commit或git add的状态 git checkout -- file [-- 非常重要] # 将暂存区的修改回退到工作区 git reset HEAD <file> #撤销修改小结[前提: 都只是在自己本地代码库中] 场景1: 改乱了工作区某个文件的内容,想直接丢弃工作区的修改内容 git checkout -- file 场景2: 不仅改乱了工作区的文件,还添加到了暂存区,想放弃修改 git reset HEAD file 回到场景1 场景3: 提交到不合适的修改到版本库,要撤销本次提交 git reset commit_id # 删除文件 git rm file # git 与 github # 添加远程库 [先有本地库,后有远程库时,关联操作] # 1. github上添加SSH # 2. 创建repository # 3. git remote add origin git@github.com:blingyuan/learngit.git [关联一个远程库] # 4. git push -u origin master [初次, 远程master上为空, 加上-u参数,git会把本地master推送到origin/master上,并关联] # 5. git push origin master [之后, 将本地推送到远程 就可以不加-u参数] # 从远程库克隆 [从零开发, 先创建远程库,然后从远程库克隆] # 1. 在github上创建repository # 2. git clone git@github.com:blingyuan/learngit.git [克隆出一个本地库] # github 支持多种协议, git://使用 ssh , 也支持https协议 # https协议速度慢,每次推送还必须输入口令,但某些公司只开放http端口,就只能使用https # git 分支 # 一. 创建/合并分支 # 创建dev分支, 切换到dev分支 git checkout -b dev # 查看当前分支 git branch [*表示当前head的位置] # 在当前分支进行修改,然后添加到暂存区,提交,切换到主分支,合并,提交到远程分支,删除分支 git add readme.txt; git commit -m ""; git checkout master; git merge dev; [进行merge时, master分支没有修改, 进行"快速合并/fast forward"] git push origin master; git branch -d dev # 二.解决冲突[进行merge时, master分支有进行过修改, 无法进行"快速合并"] # 查看冲突文件 1.git status 2.打开冲突文件,解决冲突,重新add并commit 3.git log --graph --pretty=oneline --abbrev-commit[查看分支合并情况] # 三. 分支管理策略 # fast forword模式下, 删除分支后,会丢失分支信息 # 如果要强制禁用 fast forward模式,git会在merge时重新生成一个新的commit,就可以看出分支信息 1. git checkout -b dev 2. git add readme.txt 3. git commit -m "" 4. git checkout master 5. git merge --no-ff -m "" dev [使用--no-ff禁用fast forward模式,此时merge时要加 -m 描述, 因为是创建一个新的commit] # 在实际开发中,应该遵循的几个基本原则 # 1. master分支应该是非常稳定的,仅用来发布新版本,平时不能在上面干活 # 2. 每个人有自己dev分支 # 四. Bug分支[修复bug] # 情景: 当有bug[代号001]产生,此时手上dev分支的readme.txt[之前被git add/git commit过]文件还没修改完,不能进行commit,有个新建的文件 test.txt[没有被git add/git commit过],但是master分支有个紧急bug需要处理,要切换分支 # 正确步骤:[保留现场] 1. git add test.txt[新建的文件时未被追踪的文件, 需要让他被git追踪] 2. git status [on branch dev, new file: test.txt, modified: readme.txt] 3. git stash [保留现场,saved working directory] # 切换到需要修复bug的分支,创建对应的bug分支,修复,add, commit, merge,delete 1. git checkout master[在master分支上修复bug] 2. git checkout -b issue-001[创建bug分支, 修复readme.txt文件] 3. git add readme.txt 4. git commit -m "fix bug 001" readme.txt 5. git checkout master 6. git merge --no-ff -m "merge bug 001" issue-001 # bug修复完, 切换到dev分支, 继续工作,恢复 1. git checkout dev 2. git stash list # 恢复方法 1. git stash apply[恢复后,但内容不删除] + git stash drop[删除stash] 2. git stash pop[恢复的同时删除stash内容] # 小结: 修复bug时,会通过创建新的bug分支进行修复,然后合并,最后删除 # 当手头工作没有完成时, 先将工作现场git stash一下,然后去修复bug,修复后再git stash pop,回到工作现场 # 五. Feature分支[添加新功能] # 情景: 添加新功能时,会有一些实验性质的代码. 一般每添加一个新功能,创建一个feature分支,开发,完成后,合并,删除feature分支 # 假设现在接到一个新任务,开发"feature-001" 1. git checkout -b feature-001 2. git add feature-001.txt 3. git commit -m "add feature-001" # 开发完成, 切换到dev分支, 准备合并 4. git checkout dev # 此时, 上级命令,新功能取消,分支销毁 5. git branch -d feature-001 [error: the branch is not fully merged, 此时分支还没合并,如果删除,将会丢失] 6. git branch -D feature-001 [使用大写的-D参数,强行删除] # 小结: 开发一个新的feature,最好新建一个分支 # 如果丢弃一个还未合并的分支,可以使用 git branch -D <name>强行删除 # 六. 多人协作 git remote [查看远程库的信息] git remote -v [查看更详细的信息 fetch/push地址] # 推送分支 1. git push origin master [将本地的master分支推送到远程的origin分支上] # 要推送其他分支,如dev 2. git push origin dev # 哪些分支需要推送 #1. master分支是主分支,要时刻与远程同步 #2. dev是开发分支,团队成员都在上面工作,也需要与远程同步 #3. bug分支用于在本地修复bug,没必要推送到远程 #4. feature分支是否推送,取决于是否有其他小伙伴一起开发 # 抓取分支 # 情景: 一个小伙伴要参与开发,要先clone项目, 要在dev分支上进行开发,必须创建远程origin的dev分支到本地,在dev上进行修改,时不时push到远程[远程有dev分支] 1. git clone git@github.com:blingyuan/learngit.git 2. git checkout -b dev origin/dev [本地创建dev分支,并与远程的dev分支关联] 3. git add env.txt 4. git commit -m "add env" 5. git push origin dev # 小伙伴向origin/dev分支推送了她的提交,另一位小伙伴也修改了文件,并试图推送 6. git push origin dev [error: failed to push, git pull before pushing again] # 推送失败, 先 git pull把最新的提交从origin/dev抓取下来,在本地合并,解决冲突,再推送 7. git pull[如果 git pull也失败,是没有本地的dev分支与远程origin/dev的连接,设置连接] 8. git branch --set-upstream-to=origin/dev dev 9. git pull [重新pull] # 多人协作的工作模式,一般是: 1. 试图用 git push origin <branch-name>推送自己的修改到远程 2.如果推送失败,是因为远程分支比本地的新,需要先git pull试图合并 3.如何合并有冲突,则解决冲突,并在本地提交 4.如果没有冲突或者解决冲突后,再用 git push origin <branch-name>进行推送 如果 git pull时提示no tracking information,则说明本地分支和远程分支之间的链接关系没有建立,用命令 git branch --set-upstream-to <branch-name> origin/<branch-name> # 小结: # 1. 查看远程库信息, git remote -v # 2. 本地新建的分支如果不推送到远程, 对其他人是不可见的 # 3. 从本地推送分支, 如果git push origin branch-name, 如果推送失败,先用git pull抓取远程新的提交 # 4. 在本地创建的远程分支对应的分支,使用git checkout -b branch-name origin/branch-name, 本地和远程分支的名字最好一致 # 5. 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name # 6. 从远程抓取分支,使用 git pull,如果有冲突,要先处理冲突 # 标签管理 # 一般发布一个版本,通常在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来可以根据标签取出对应时刻的历史版本。 # 所以,标签也是版本的一个快照 # 提问: 为什么有commit,还要引入tag # 因为commit_id是一串hash值,不好找,tag是一个容易让人记住的有意义的名字,它是跟某个commit绑定在一起的 git tag <name> git tag v1.0 [打标签,这样默认是打在最新提交的commit_id上的] git tag [查看所有标签,标签不按时间顺序列出,而是按字母排序] # 场景: 忘记打标签了,又有新的commit了,怎么给以前的commit_id打标签 # 方法: 找到历史提交的commit_id,打上就可以 git log --pretty=oneline --abbrev-commit [查看提交日志] git tag <tag_name> <commit_id> [给某个commit_id打tag] # 创建带有说明的标签,-a指定标签名, -m指定说明文字 git tag -a <tagname> -m "version 0.1 released" commit_id git show <tagname> [查看说明文字] git tag -d <tagname> [删除标签] # 创建的标签都只存储在本地,不会自动推送到远程 git push origin <tagname> [将标签推送到远程] git push origin --tags [一次性推送全部未推送到远程的本地标签] # 如果要删除远程的标签 1. 先从本地删除 git tag -d <tagname> 2. 从远程删除[push] git push origin :refs/tags/<tagname> 链接: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000