在使用git之前,一直用的是svn版本管理;与svn最大不同的是,git有两个仓库,一个是本地仓库,一个是服务器上共享的仓库;本地仓库是每个开发者自己独有的,即使commit提交也只是提交到本地仓库;这只是git流行起来的一个优势之一,另外linux作者开发的这套版本管理工具,很接地气,也是流行起来的一大亮点。扯了这么多没用的,言归正卷,那么在日常开发工作中,哪些git命令是我们常用到的呢?下面就说说几个常用命令的常用场景,至于这些命令详细使用就不在本文讨论之内。
1、git命令别名
使用过git的都知道,git的有些命令名有些长,每次在使用改命令时都要输入这些,尤其是一些命令语句;怒长的一串文字字符串打起来很费劲,开发者也很不爽;这时我们的git alias功能可以费墨登场了。下面是本人的一些常用命令的alias配置:
命令 | 别名 |
commit | ci |
checkout | co |
status | st |
merge origin/master | mom |
注意:以上git命令别名的设置是在计算机用户目录下.gitconfig文件全局设置的,这样所有git分支都能运用设置的别名。当然,根据不同开发者的个人喜好,可以有自己的别名设置;
2、git checkout
这个命令用于检出某个分支、提交或者对应的某个分支、提交的文件。根据不同的参数来检出不同的内容;那么其常用场景如下:
- git checkout . 用暂存区的内容覆盖当前工作区内容,那么可以达到用暂存区的内容来撤销本地分支的修改
某些情况下,想在当前分支中做一下测试,这时修改了当前分支的多个文件,测试过后要撤销对当前分支的变更,这时可以使用git checkout . 命令;
注意:使用该命令需要注意一点:本地分支所有文件的变更都会被撤销 - git checkout -b newBranchName origin/master 基于master创建一个新分支,并切换到新分支上
避免了git branch完成此功能需要多执行一步:
git branch newBranchName origin/master
git checkout newBranchName - git checkout - 切换到 切换到当前分支之前的分支
使用场景:开发本地创建多个分支来完成不同的需求,这时可能需要来回切换不同的分支,如在A分支开发时,提测的B分支有bug,qa要让fixed,这时就切换到B分支屁颠屁颠的修bug,完事之后要切换到A分支,此时可以使用快捷命令 - git checkout commitId/branchName -- path 用指定的提交id或者分支的某个文件来替换本地与其对应的文件,达到该文件的内容变更的撤销
使用场景:由于某种原因,在众多的文件变更中,只撤销某个指定文件的内容变更
3、git stash
该命令用于暂存本地文件的修改。
某天,开发者在一个分支上开发某个需求,突然这种自我happy的开发方式被打断,某个提测的分支有bug需要马上修复;擦,本地的代码还没有提交呢,但是又不想因临时的提交本地代码导致如何描述临时提交的描述。于是乎就可以使用git stash来存取本地变更的代码;然后切换有bug的分支解决问题,最后回到本分支使用git stash pop即可复现之前没有提交的本地变更代码;该命令是不是用起来很爽。
但是,使用该命令需要注意以下两点:
- git stash只是保存已经git add过的文件变更,只要暂存过的文件都会被保存;那么本地新增的文件,必须使用git add命令之后才会被保存,否则提示你需要将新增文件要暂存;
- 暂存的分支需要使用git stash pop恢复;但是若多次git stash,需要准确记住某个分支的对应的保存位置,否则容易搞错;可以使用 git stash list来查看;
4、git revert
用于撤销某次提交的变更内容。这个revert与webstrom等IDE中提供的revert掉git的某些文件不同,后者其实最终还是利用git checkout来实现的。
该命令的最大场景是:代码发布上线后,由于某种原因需要代码回滚,这时基于当前分支发布的分支在线上代码回滚后merge master时,本地新开发的需求代码丢失了,因为回滚到上线之前的代码,这个时候还不存在回滚掉的代码;怎么恢复merge掉的代码呢,这时就需要git revert了,具体步骤如下:
- 通过git reflog查看回滚生成的commit,如下图本地曾经回滚过的日志,e103c47是回滚时新生成的提交点
- 使用命令 git revert e103c47即可恢复merge掉的代码
5、git reset
该命令用于重置指定区域的内容,可以操作提交,也可以操作文件;该命令的三个参数--hard、--mixed、--soft表示重置的范围,这个命令也是最常用的命令之一;
使用该命令得记住一点,它会对git的提交历史做修改,可能会删掉一些历史提交点导致不能恢复。
- git reset [--mixed] commitId 用commitId的内容重置暂存区的内容,工作区内容不会被覆盖,这样可达到撤销暂存区的变更;
场景:某次变更的代码一不留意用git add添加到暂存区,但是想要撤销暂存区的内容而不会导致本地工作区代码丢失,这时可以使用git reset HEAD - git reset --hard commitId 用commitId的内容重置暂存区和工作区的内容
场景:在某次升级某个稳定性不确定但是功能全面的框架,使用包管理机制下载最新的框架源码,开发一段时间后发现有很大问题,但是这时代码已经git add到暂存区,想要撤销掉工作区和暂存区的内容变更时,就可以使用git reset --hard HEAD - git reset commitId -- path 用指定commitId的文件内容替换掉暂存区对应文件,工作区的不便;
注意:该操作不会修改git的提交历史
6、git branch
用于创建、显示分支等与分支相关的命令,工作中常用到的情况:
- git branch branchName origin/master 基于master创建一个分支
这种情况创建的分支要进行完整的开发,过程有些繁琐,需要:
git checkout branchName //切换到新建的分支上 git push //将当前分支推送服务器 git branch -u origin HEAD //建立当前分支与服务器同名分支的上传流
但是在实际中,个人比较倾向于下面一种,只需两步即可:
git checkout -b branchName origin/master git push -u origin HEAD
- git branch -vv 查看本地分支的upstream的对应情况,一定要确保本地分支与服务器上分支的对应情况,因为不单独设立对应情况,新建分支默认与master是对应关系
- git branch -remote 查看的是本地仓库的所有分支
- git branch -D branchname 删除本地分支
注意:需要切换到其他分支进行其操作,不能在当前分支删除当前分支,这是不允许的
7、git push
用于与服务器仓库同步代码,该命令的用法不做赘述,该命令的一个常用情况就是删除服务器端某个指定的分支,命令如下:
git push origin 空格:remote_branch_name
8、git rm
该命令用于删除分支中的文件,他可以只删除暂存区的文件,也可以同时删除暂存区和工作区的文件,参数不同,决定删除的文件范围也不同,具体如下:
git rm --cached filename //删除暂存区的某个文件,工作区的不会删除 git rm filename //同时删除暂存区和工作区的该文件
git rm filename的场景:为满足某次需求,新增了一些代码文件,在开发中可能不小心将某个无用的新文件加到工作区而被git add到暂存区,这时需要同时删掉暂存区和工作区的该文件;
9、git commit
用于提交暂存区代码到本地仓库;说一下git commit --amend选项
git commit --amend 的使用场景:某次需求开发提交中,由于某种原因导致提交的结果不是期望的,需要重新提交,但是又不希望前一次的提交使git提交历史树变长,那么可以使用git commit --amend来用暂存区的内容修正前一次的提交。 如果不使用带--amend的提交,结果是git提交历史树会变长。git commit --amend的原理图如下:
10、git blame
在多人协作开发的项目中,想要知道某个文件的历史改动情况,可以使用该命令来完成,具体如下:
git blame -L line1, line2 file
上面是查看file文件的第line1行到line2行代码的改动情况,如下图是查看本地某个文件的192到193行的改动情况,看出是adam23有最新改动
上面介绍的都是自己用的比较频繁的git命令和对应的场景,当然有些情况不一定值得借鉴,或者还有不妥的地方,这些都希望大家批评指正!!
11、.gitignore诠释
使用.gitignore时,可能会发生这样一种情况:明明在.gitignore中设置了忽略某个文件,可以用git status查看时还是会追踪其变化*;遇到这种情况,如果想当然的认为配置到`.gitignore`中的文件不会被追踪,那么可能是你对.gitignore的有误解。
那么.gitignore的具体理解是什么样呢,具体有两个方面需要注意:
- .gitignore只会忽略从未在git仓库中维护的文件,即*自文件添加以后,从未 add 及 commit 过的文件*;这时`.gitignore`中配置的文件是有效的,即git不会追踪其变化。
- 已经在git仓库维护过的文件,即使在`.gitignore`中配置不要追踪其变化,一旦文件变化git还是会追踪的。
通俗的说,就是`已经维护起来的文件,即使加上了gitignore,也无济于事`
了解上面的情况,才算是对.gitignore真正的理解。那么问题来了:**如何忽略对git仓库中已维护文件的变化的追踪呢?**
答案是使用:git update-index --assume-unchanged path。例如git仓库中已维护logs目录,想忽略该目录下的所有.js文件的变化,可以这样:
git update-index --assume-unchanged logs/*.js
具体可以参考这里