在sourceTree上提交代码习惯了,背后的原理却不知道。当你学会了git 命令,代码管理游刃有余,你会很开心的。 不说了,快study吧。
在学习git之前需要搞清楚的一个重要问题是了解git的版本库为何?
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
如图
git的工作区和版本库示意图
你在本地对程序的修改是在工作区,一旦用git add添加到版本库,会先添加子stage(暂存区),等使用了git commit后才会提交到当前分支上。然后gti push才会到达远端仓库。别人git pull之后你的代码别人就能看到了。
一旦提交到版本库或者贮藏(git stash)到暂存区,你的内容就不会再丢失了。个人感觉:git add. 和git stash都是讲文件存在暂存区,但是位置不一样。
不信你看下面的例子:
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: READMECIM.md
modified: RELEASE.md
modified: src/main/java/com/navi/rtit/service/CoordTransformService.java
modified: src/main/java/com/navi/rtit/service/impl/CoordTransformServiceImpl.java
modified: src/main/java/com/navi/rtit/service/impl/DefectCodeServiceImpl.java
modified: src/main/resources/application-prod.properties
modified: src/main/webapp/WEB-INF/jsp/login-lte.jsp
modified: src/main/webapp/WEB-INF/jsp/main-lte.jsp
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git stash list
stash@{0}: On master: BURR转坐标
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git log
commit 66c73caa62769d861fd3eb3941f8520640a152f9 (HEAD -> master, origin/master, origin/HEAD)
Author: Matthew <452562133@qq.com>
Date: Mon Mar 2 17:42:42 2020 +0800
更新为最新代码
commit d066c2a628c5384fe521e91ab365ca2e1dbda959
Author: Matthew <452562133@qq.com>
Date: Mon Feb 24 20:53:51 2020 +0800
init
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git reset --hard 66c73caa62769d861fd3eb3941f8520640a152f9
HEAD is now at 66c73ca 更新为最新代码
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git stash list
stash@{0}: On master: BURR转坐标
首先我是git stash 了我的代码,然后git add.,然后重放到上一个版本。然后git status 空空如也,但是git stash list 的内容已经存在。因此正面git add和git stash存放在暂存区的不同位置(如有不对,帮忙指正)
另外一个比较重要的问题是: 要理解git管理的是修改,而非某一个具体文件,举个例子,有一个文件你修改后,git add然后再次修改该文件,然后git commit。然后git status你会发现你的第二次修改并没有被commit到版本库中,为什么呢?因为git是不允许直接从工作区commit到版本库的的分支上,必须从暂存区才能git commit。这也验证了git并不是以文件来提交的,如果以文件提交则第二次的修改也会被commit的。
常见的命令如下:
-
git config --global user.name "你的名字" 让你全部的Git仓库绑定你的名字
-
git config --global user.email "你的邮箱" 让你全部的Git仓库绑定你的邮箱
-
git init 初始化你的仓库
-
git add . 把工作区的文件全部提交到暂存区
Note: 从整理看到git是很聪明的,它在引导你下一步干什么,例如git status后,看到你的代码没有提交就会引导你 git add/checkout --。而如果你git add后则提示你可以git reset HEAD <file>
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: READMECIM.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: READMECIM.md
modified: RELEASE.md
modified: src/main/java/com/navi/rtit/service/CoordTransformService.java
modified: src/main/java/com/navi/rtit/service/impl/CoordTransformServiceImpl.java
modified: src/main/java/com/navi/rtit/service/impl/DefectCodeServiceImpl.java
modified: src/main/resources/application-prod.properties
modified: src/main/webapp/WEB-INF/jsp/login-lte.jsp
modified: src/main/webapp/WEB-INF/jsp/main-lte.jsp
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git add .
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: READMECIM.md
modified: RELEASE.md
modified: src/main/java/com/navi/rtit/service/CoordTransformService.java
modified: src/main/java/com/navi/rtit/service/impl/CoordTransformServiceImpl.java
modified: src/main/java/com/navi/rtit/service/impl/DefectCodeServiceImpl.java
modified: src/main/resources/application-prod.properties
modified: src/main/webapp/WEB-INF/jsp/login-lte.jsp
modified: src/main/webapp/WEB-INF/jsp/main-lte.jsp
另外如果工作区的内容没有git add的话直接git stash是啥情况呢?
$ git stash save 'newBurr'
Saved working directory and index state On wxdev: newBurr
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (wxdev)
$ git status
On branch wxdev
nothing to commit, working tree clean
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (wxdev)
$ git stash list
stash@{0}: On wxdev: newBurr
stash@{1}: On wxdev: dev_BURR坐标转换
stash@{2}: On master: BURR转坐标
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (wxdev)
可以看到确实stash成功了,只不过和正常git add 然后git stash的提示不太一样,这一点还不是很懂。
-
git add ./<file>/ 把工作区的<file>文件提交到暂存区
-
git commit -a "xxx" # git add xxx && git commit 将工作区的文件写入暂存区并提交到本地的仓库区
-
git remote add origin https://github.com/name/name_cangku.git 把本地仓库与远程仓库连接起来
-
git push -u origin master 把仓库区的主分支master提交到远程仓库里
-
git push -u origin <其他分支> 把其他分支提交到远程仓库
-
git status查看当前仓库的状态
-
git diff 查看文件修改的具体内容
-
git log 显示从最近到最远的提交历史。
Note: git log --pretty=oneline 精简化显示log ,还有很多参数
-
git clone + 仓库地址下载克隆文件 <堪称神器,只要是开源的项目直接clone到本地看源码>
git clone --recursive 用于循环克隆git子项目
克隆ansible 项目 git clone https://github.com/ansible/ansible.git --recursive
-
git reset --hard + 版本号 回溯版本,版本号在commit的时候与master跟随在一起。版本号可以用git reflog来查看,可以穿梭到任何版本,这个需要特别注意,重放前的代码如果没有贮藏过那么代码就不见了,那么你就悲催了。
Note:1、默认HEAD指向上一个版本。
$git log --pretty=oneline
66c73caa62769d861fd3eb3941f8520640a152f9 (HEAD -> master, origin/master, origin/HEAD) 更新为最新代码
d066c2a628c5384fe521e91ab365ca2e1dbda959 init
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git reset --hard
HEAD is now at 66c73ca 更新为最新代码
2、
-
git reflog 显示命令历史,记录所有HEAD的历史,git commit checkout 等操作会记录在log中。
如果不小心将未stash的代码gie reset了们可以通过查找commit id就回工作区的内容。
-
git checkout -- <file> 撤销命令,用版本库里的文件替换掉工作区的文件。我觉得就像是Git世界的ctrl + z
Note:1、 对应sourceTree的操作就是丢弃
2、从来没有被添加到版本库就被删除的文件,是无法恢复的(这点是有亲身体会的,所以希望加引以为戒,最好经常贮藏自己的代码,或者提交到自己的分支上)
3、git checkout -- file
命令中的--
很重要,没有--
,就变成了“切换到另一个分支”的命令。
4、如果你不下心删除了(对应sourcetree中也有一个删除的操作,)可以用这个命令恢复。
$ git checkout -- test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
-
git rm 删除版本库的文件
-
git branch 查看当前所有分支
比较有用,每次提交前一定要确认 你现在所处的分支是啥,不要把没改完的代码提交到即将要推向远端的仓库。
-
git branch <分支名字> 创建分支
-
git checkout <分支名字> 切换到分支。注意和git checkout -- <file>区分
这里需要吐槽一下SVN切换分支的操作,太慢。而git很快,瞬间完成,其实就是一个HEAD指针指向的改变,因此比较快。
你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
$ git branch
* master
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git branch wxdev
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git branch
* master
wxdev
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
$ git checkout wxdev
Switched to branch 'wxdev'
A READMECIM.md // A ->ADD
M RELEASE.md // M -> Modify
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (wxdev)
$ git branch
master
* wxdev
注意:git checkout命令加上-b参数表示创建并切换
例如 git checkout -b wxdev就省去了git branch 和git branch <name>
另外
$ git switch -c dev 创建并切换到新的dev分支比上面的命令好理解,毕竟关键字就可以看出来 switch 和-c(create)
-
git merge <分支名字> 合并分支, 合并到当前分支,先切到master 分支,然后git branch <分支名>这样就merge 你的分支到master分支了。Fast-forward 值得注意,这次合并是“快进模式”,也就是直接把
master
指向dev
的当前提交,所以合并速度非常快。
$ git merge wxdev
Updating 66c73ca..6389fd4
Fast-forward
READMECIM.md | 8 ++
RELEASE.md | 3 +
.../navi/rtit/service/CoordTransformService.java | 2 +
.../service/impl/CoordTransformServiceImpl.java | 131 ++++++++++++++++-----
.../rtit/service/impl/DefectCodeServiceImpl.java | 7 ++
src/main/webapp/WEB-INF/jsp/login-lte.jsp | 4 +-
src/main/webapp/WEB-INF/jsp/main-lte.jsp | 4 +-
7 files changed, 125 insertions(+), 34 deletions(-)
create mode 100644 READMECIM.md
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
-
git branch -d <分支名字> 删除分支,有可能会删除失败,因为Git会保护没有被合并的分支
-
git branch -D + <分支名字> 强行删除,丢弃没被合并的分支
-
git log --graph 查看分支合并图
-
git merge --no-ff <分支名字> 合并分支的时候禁用Fast forward模式,因为这个模式会丢失分支历史信息
Note:1、推荐使用此种方式合并
$ git merge --no-ff -m 'merge with no-ff' wxdev
Merge made by the 'recursive' strategy.
RELEASE.md | 1 +
1 file changed, 1 insertion(+)
$ git log --graph --pretty=oneline --abbrev-commit
* 0da9975 (HEAD -> master) merge with no-ff
|\
| * 0117e27 (wxdev) 版本更更新
|/
* 6389fd4 BURR坐标准换
* 66c73ca (origin/master, origin/HEAD) 更新为最新代码
* d066c2a init
DESKTOP-LDIM22E+wx@DESKTOP-LDIM22E MINGW64 /e/work1/qms (master)
2、no --ff这种方式也是souretree 里面合并分支的常用方式。
-
git stash 当有其他任务插进来时,把当前工作现场“存储”起来,以后恢复后继续工作(git stash前一定要先git add到暂存区)
-
git stash show 宏观上观察贮藏中哪个文件被修改
-
git stash show -p 查看某个stash的的详细内容,默认看的是stash@{0}:
-
git stash list 查看你刚刚“存放”起来的工作去哪里了
-
git stash apply 恢复却不删除stash内容
Note :有多个版本的stash时候,需要指定版本号,例如git stash apply stash@{1}。其他stash 这样查看
git stash show stash@{$num} -p
E:\work1\rt>git stash list
stash@{0}: On master: release1
stash@{1}: On master: release
stash@{2}: WIP on master: 3f99c64 '*<E6><96><B0><E5><A2><9E>BI<E6><95><B0><E6><8D><AE><E6><BA><90>'
-
git stash drop 删除stash内容
-
git stash pop 恢复的同时把stash内容也删了(谨慎使用,如果觉得stash的内容过多,可以过一段时间手动用git stash clear清空)
Note:1、可以使用git fsck --lost-found恢复被删除的
$ git fsck --lost-found
Checking object directories: 100% (256/256), done.
Checking objects: 100% (175/175), done.
dangling blob 36422755e49379309004079c1bec2b6d43d3ef0f
dangling blob 644c62fb200d7d7957f46373c4ae0993cb480a22
dangling commit bf9626d8093e724770d012d68d020018770605bf
dangling commit f0961d829f9a48a9fd8dc8c3cd9be7773259cc1a
dangling blob 42170bad0627e4c4b1722a59d3b7489ba1a62d60
dangling commit 58dbde7671085153b5dc2610e31626fdf3012900
dangling commit d1cbe7ee8ff16d507d68c5af3f6575046bb32106
2、 "dangling commit ..."你可以理解为你stash的id
3、git show <ID>
4、选择要恢复的ID,然后git merge <ID>
-
git remote 查看远程库的信息,会显示origin,远程仓库默认名称为origin
-
git remote -v 显示更详细的信息
-
git pull 把最新的提交从远程仓库中抓取下来,在本地合并,和git push相反
-
git rebase 把分叉的提交历史“整理”成一条直线,看上去更直观
-
git tag 查看所有标签,可以知道历史版本的tag
-
git tag <name> 打标签,默认为HEAD。比如git tag v1.0
-
git tag <tagName> <版本号> 把版本号打上标签,版本号就是commit时,跟在旁边的一串字母数字
-
git show <tagName> 查看标签信息
-
git tag -a <tagName> -m "<说明>" 创建带说明的标签。-a指定标签名,-m指定说明文字
-
git tag -d <tagName> 删除标签
-
git push origin <tagname> 推送某个标签到远程
-
git push origin --tags 一次性推送全部尚未推送到远程的本地标签
-
git push origin :refs/tags/<tagname> 删除远程标签<tagname>
-
git config --global color.ui true 让Git显示颜色,会让命令输出看起来更醒目
-
git add -f <file> 强制提交已忽略的的文件
-
git check-ignore -v <file> 检查为什么Git会忽略该文件
git pull 从远程拉取最新版本 到本地 自动合并 merge git pull origin master
Note:如果两个或者几个人都修改了某一个文件 直接git pull 会在你不知对面提交了什么的情况下直接merge到local,虽然会在代码上show出, merge 戳,需要人为来处理。
git fetch 从远程获取最新版本到本地 ,不会自动合并 merge
git fetch origin master
git log -p master ../origin/master git merge orgin/master
-----update 2020年4月26日15:10:52-----
如何查看从远端拉去的代码内容修改了啥?
git log -p -1 查看最近1次的文件变更 -2 就是倒数第二次的
实际使用中 使用git fetch 更安全 在merge之前可以看清楚他人到底提交了啥?你确认要merge再pull下来。
参考地址:帐号已迁移