在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 更新为最新代码
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下来。
参考地址:帐号已迁移