概述

其实git的基本用法已经掌握,但是目前未参与过正规的大型项目开发。对于其中的一些git命令不是特别了解,比如git tag命令,我们一般不打tag。比如git rebasegit revert区别。

关于删除git rm

我们新建一个项目之后,一般会添加一个.gitignore的文件,忽略不被追踪的文件和文件夹。然后执行git init。或者在远程仓库建立一个project,pull到本地,然后初始化代码。

问题是,我们用IDE产生的一些本机配置文件,不应该被追踪,如果我们已经git addgit commit将这些本机配置加入追踪了。那么如何删除呢?或者我们做web项目,一般有个target/文件夹,假如别人已经加入追踪了,如何删除呢?
其实挺简单,普通的删除,如果使用linux命令的话是rm a.txt,对应的git命令就是git rm --cached *.iml,删除目录对应的就是git rm -r .idea/--cached的作用是,只删除暂存区,不删除工作区,如果不带这个参数,则表示都删除。 工作区表示没有git add的存储区域,暂存区表示已经git add的存储区域

关于 git diff

git diff用于查看还未commit的改动,如果我们使用IDE开发软件,其实IDEA的Version Control功能很好用,用不到这个命令。如果在服务器上改动代码,或者在无IDE的机器上用编译器写代码,这个命令就很好用了。

# 查看工作区与暂存区的差别(这里只显示未被执行`git add`的文件)
git diff
# 查看暂存区与版本库的差别(这里只显示已经被执行`git add`的文件)
git diff --cached
# 查看工作区与版本库的差别(这里只显示未被执行`git commit`的文件)
git diff HEAD
# 查看工作区与版本库的差别,只显示改动的文件名,不加`--stat`表示显示明细
git diff HEAD --stat
# 只查看一个文件,工作区与版本库的差别
git diff HEAD -- src/main/java/com/jiler/utils/MyDateUtils.java

还可以用于对比两个分支的差距。

# 以master为基准,看dev做了哪些修改,
git diff master dev
# 以master为基准,看dev修改了哪些文件
git diff master dev --stat
# 以master为基准,看dev的MyDateUtils文件修改了啥
git diff master dev src/main/java/com/jiler/utils/MyDateUtils.java

撤销修改

如果修改的代码还未执行git add,则用如下命令可以撤销工作区的改动。相当于删掉修改的代码。

git checkout -- src/main/java/com/jiler/utils/MyDateUtils.java

如果修改的代码已经执行git add,还未执行git commit,则用如下命令可以撤销缓存区的改动,把改动放回工作区。不会删除对代码的改动,如果要想删除修改的代码,可以继续执行上述命令。

git reset HEAD src/main/java/com/jiler/utils/MyDateUtils.java

git stash

正在开发,有的文件已经被add 有的文件没被add,甚至有的文件还没被track。这时候出线上bug了,就需要用到这个命令了。

# 查看stash栈中的列表
git stash list
# 将已经被track的文件改动暂时保存到栈顶
git stash
# `-u`表示没有被track的文件也会被stash起来
git stash -u
# 释放最顶层的栈元素。还有个命令`git stash apply`只应用代码改动,不删除栈顶元素。没想到场景,就不解释了
git stash pop
# 丢弃最顶层的栈元素
git stash drop
# 使用标号`stash@{0}`,直接使用栈的某个元素
git stash apply stash@{0}

不太常用

不太常用,但是很有用的命令如下

# 生成公钥私钥
ssh-keygen -t rsa -C "jilerwu@icloud.com"
# 配置git全局
git config --global user.name "wujunpeng"
git config --global user.email "jilerwu@icloud.com"
# 从远程拉取本地不存在的分支
git fetch origin wjpdev:wjpdev
# 删除远程分支关联(-D表示强制删除)
git branch -d -r origin/branch-name 
# 打印git提交日志,每个commit一行
git log --pretty=oneline
# 以图的形式展示merge日志
git log --graph --pretty=oneline
# 直接跳转到某个commit的位置(--hard表示丢弃修改)
git reset --hard 7f96eb88dc
# 直接跳转到某个commit的位置(--soft表示保留所有修改)
git reset --soft 7f96eb88dc
# 快捷跳转到上一个提交
git reset --hard HEAD^
# 撤销某一个commit内容,与reset的区别是revert是用一次新的commit去抵消之前的代码修改
git revert 7f96eb88dc
# 本次仓库与远程同名参考建立联系(适用于本地先创建,远程后创建仓库)
git remote add origin git@github.com:jiler/jiler.github.io.git
# add origin 后第一次应该使用如下命令推送master到远程
git push -u origin master
# 查看关联名
git remote -v
# 删除关联 origin
git remote rm origin
# 查看执行命令的历史
git reflog

关于git tag

用于跟某个commit绑定,容易查找代码。比如可以用tag表示版本信息。

# 切换到对应分支,然后给当前commit打标签version1.0,可以给一个commit打两个标签
git tag version1.0
# 给指定commit打标签,用-a指定标签名,-m指定说明文字。
git tag -a version1.0 -m "打版本1.0的标签" e7c1fbedcdfd
# 把标签推送到远程,如果不推送到远程,默认都是在本地
git push origin version1.0
# 把所有标签都推送到远程
git push origin --tags
# 删除本地标签
git tag -d version1.0
# 删除远程标签(允许不删除本地,直接删除远程标签)
git push origin :refs/tags/version1.0

关于git rebase

之前从没关注过这个功能,其实就是为了好看。就是为了把commit日志换成一条直线,详细描述详见git教程

用我自己的话叙述就是:master分支,你checkout一个dev,然后其他人这时候往master合并代码。这时候你如果使用git rebase origin/master命令的话,相当于把你的dev以当前master作为基准,在此基础之上commit信息。当然,有冲突就解决冲突。解决冲突后,用git add .git rebase --continue合并,或者用git rebase --abort放弃干脆用merge命令重来。

todo wujunpeng 明天测试一下,两个分支commit时间对于当前master作为基准这句话是否有影响。

如果没有强制要求,我不会选择git rebase dev代替git merge dev,因为会造成一些问题。

比如另外一个RD,开发了一个小功能,属于锦上添花的,合并到了master。他合并之前,你已经checkout了自己开发分支wjp-dev,如果不用git pull origin master或者git merge origin/master,而是使用git rebase origin/master,这时候你的代码就永远混入了别人的代码,你永远找不到rebase操作之前的代码了。大家使用rebase命令的前提是:共同写代码的同事能力还不错。可是一旦这个人锦上添花的小功能出bug,而又不能及时修复,而你开发的功能比较重要,不能下线,这时候很难受的。也就是说,虽然跟你合作的同事,代码已经合并到master,但是这个人是不完全被信任的,工作中是一定会遇到这种情况的。