git操作详解

 

一、git的工作区&版本库&远程库的关系

1.1 工作区(Working Directory):

就是你在电脑里能看到的目录,比如我的fork-common-autotest文件夹就是一个工作区:

 

 

1.2 版本库(Repository):

工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

 

1.3 远程库(origin Repository):

你在没有push之前,你操作工作区&版本库只是你的本地库,别人是看不到的,只有本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程,你才和远程库同步

二、管理修改

2.1 添加文件

把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit -m "message" 提交更改,实际上就是把暂存区的所有内容提交到当前分支。

2.2 查看修改

在这两步之前,你在工作区修改文件,可以用git status 查看工作区的状态:

 

not staged for commit 表示是版本库跟踪过(add过),但是还没有保存到暂存区去提交的文件

git 给出了相关操作命令:

git add <file> 是将工作区的某修改文件加到暂存区

git checkout --<file> 是丢弃工作区中某文件的的修改

untracked 表示未被跟踪的文件,即未曾add过,提交到版本库到文件,可以用git add 命令添加提交

PS:如若你想提交所有track过的改动文件,可以直接使用git commit -am "<message>",将所有修改,但未进stage的改动加入stage,并记录commit信息。(某种程度上相当于git addgit commit -m的组合技,前提是被改动文件已经是tracked)

可以用git diff查看文件详细改动:

git diff 是查看所有文件的详细改动

git diff <file>是查看某个文件的详细改动

git diff <commit id>是查看当前版本和某个版本的之间的所有改动diff

git diff <commit id1>  <commit id2>是查看某两个版本之间的所有改动diff

git diff <branch1> <branch2>也可查看两个分支之间的diff

2.3 删除修改

rm <file>只是你在本地工作区删除了一个文件,如若版本库中也想删除,需要用git rm <file>

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删(可以用git checkout – <file>撤销),但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容

 

三、撤销修改

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file,想丢弃该路径下的所有修改:git checkout .

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了场景1,你可以在工作区重新修改,如若工作区也想丢弃修改,进行第二步;第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,就要进行版本回退,不过前提是没有推送到远程库。

四、版本回退

git log 命令显示从最近到最远的提交日志,谁,什么时间,提交了什么修改,commit 后的一大串字符是commit id,commit id是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id和我的肯定不一样,以你自己的为准。

 

Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交09f5e8...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100,当然这个时候用commit id 就很合适,不要用head指针去指向前几个版本。只要知道commit id ,你就可以纵横古今~

  • HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。(--hard表示:完整切换到该commit_id下,丢弃工作区改动)

  • 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

  • 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。

五、添加文件到远程库

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

第一次推送,需要在github.com建立远程库,按照提示建立一个新的git仓库,然后把一个已有的本地仓库与之关联

  • 要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git
  • 关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
  • 此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;

PS:Git使用SSH连接,当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告,你需要在你的机器上生成RSA Key,并将SSH Key公钥添加到你的git账户里。

本地用ssh-keygen生成ssh key,SSH 公钥默认储存在账户的主目录下的 ~/.ssh 目录,只需要复制xxx.pub文件内容到git账户中即可

 

六、拉取远程库

1.克隆远程库:git clone(Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。)

 

2.拉取远程库:git pull  

当本地有改动的时候:

2.1 不需要暂存本地改动:git checkout .

2.2 需要隐藏本地改动:git stash

git stash list可看到所有隐藏list

 

git stash pop 释放最新的隐藏改动

git stash clear :清空所有的隐藏list

七、分支管理

7.1 创建&合并分支

查看分支:git branch

创建分支:git branch <name>

切换分支:git checkout <name>

创建+切换分支:git checkout -b <name>

合并某分支到当前分支:git merge <name>

删除分支:git branch -d <name>

7.2 解决冲突

当Git无法自动合并分支时,就必须首先解决冲突:git mergetool ,解决冲突后,再提交,合并完成。

解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。

Git用<<<<<<<=======>>>>>>>标记出不同分支的内容

PS:用git log --graph命令可以看到分支合并图。

八、git 分支开发

8.1 为了怕误操作导致本地修改没有保存,你可以git checkout -b <name>重新拉一条分支自己本地开发,不用担心在master分支上开发误操作

8.2 在自己另外拉的分支上开发完成后,你可以用git cherry-pick <commit id>合并某个commit(cherry-pick是一个本地的操作)

git cherry-pick可以选择某一个分支中的一个或几个commit(s)来进行操作(操作的对象是commit)。例如,假设我们有个稳定版本的分支,叫v2.0,另外还有个开发版本的分支v3.0,我们不能直接把两个分支合并,这样会导致稳定版本混乱,但是又想增加一个v3.0中的功能到v2.0中,这里就可以使用cherry-pick了。

首先切换到你要添加commit的分支,如:你要将A分支上面的commit添加到B分支上面,我们可以要先切换到B分支上面。(注意:cherry-pick是一个本地的操作,假如你pull代码之后有人在A分支上有了新的commit,需要你先pull代码在进行cherry-pick,原因及其错误提示请见最后)

场景1: 成功的情况:Finished one cherry-pick.

场景2: 有冲突的情况:解决的冲突的方法也和普通的一样,手工检查。

场景3:使用cherry-pick出现问题:

fatal: bad object

 场景及出现错误的原因:

      我的情况是在B分支的同步A分支的一个commit,出现了如上的错误。我是直接在web上看到A分支新提交的这个commit,然后我直接在本地的B分支中进行git cherry-pick xxx。就出现了这个问题。经过尝试问题是出在了我没有切到B分支pull一下。总结过来就是git cherry-pick是本地特性,本地要有这个commit才可以被git cherry-pick

 

参考文档:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001376951885068a0ac7d81c3a64912b35a59b58a1d926b000

 

九、git版本(tag)

9.1相关操作命令

查看版本:$ git tag

创建版本:$ git tag [name]

删除版本:$ git tag -d [name]

查看远程版本:$ git tag -r

创建远程版本(本地版本push到远程):$ git push origin [name]

删除远程版本:$ git push origin :refs/tags/[name]

合并远程仓库的tag到本地:$ git pull origin --tags

上传本地tag到远程仓库:$ git push origin --tags

创建带注释的tag:$ git tag -a [name] -m ‘yourMessage’
9.2 版本和branch的区别

tag 对应某次 commit, 是一个点,是不可移动的。 
branch 对应一系列 commit,是很多点连成的一根线,有一个HEAD 指针,是可以依靠 HEAD 指针移动的。

所以,两者的区别决定了使用方式,改动代码用 branch ,不改动只查看用 tag

tag 和 branch 的相互配合使用,有时候起到非常方便的效果,例如 已经发布了 v1.0 v2.0 v3.0 三个版本,这个时候,我突然想不改现有代码的前提下,在 v2.0 的基础上加个新功能,作为 v4.0 发布。就可以 检出 v2.0 的代码作为一个 branch ,然后作为开发分支

命令:

在v2.0的commit下:git tag -a [tag name] -m "message"

git branch <tag_name> <new_branch>

git checkout new_branch

好处:不用回退版本就可开始想要的commit上开发

 

十、git reset --hard 误操作后的救命稻草

分3种情况:

1.你丢失的东西是你commit过的,找回非常简单:

1)git reflog 

b7057a9 HEAD@{0}: reset: moving to b7057a9
98abc5a HEAD@{1}: commit: more stuff added to foo
b7057a9 HEAD@{2}: commit (initial): initial commit

2)找到你要的那个commit:git reset git reset --hard 98abc5a

2.你丢失的东西是add过,但是没有commit过的,会复杂点(参考文档:https://www.cnblogs.com/hope-markup/p/6683522.html):

1)git fsck --lost-found :然后你就可以在本地项目文件中路径为.git/lost-found/other(楼主亲自试验就是这个路径)中找到它们!!并且呢,这里面包含了所有的没有被commit(指定到某次commit)的文件,甚至可能还包括你每次git add的版本

 

FYI(非必需命令): find .git/objects -type f | xargs ls -lt | sed 60q这个命令,你就可以找到最近被你add到本地仓库的60个文件

2)上个命令出来一串的字母数字,你得用编辑软件打开:拖到在sublime或者任意的编程软件中或者是google浏览器打开,就能看到每个文件的本质是啥啦!!!!!

3.你丢失的东西是你没有commit也没有add过的,congratulations!找不回来了,这是毁灭性的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值