Git学习笔记(超详细入门总结教程)

Git学习笔记(超详细入门总结教程)

本文是根据廖雪峰的教程整理而成的个人笔记,仅供学习参考之用,在此万分感谢!

1 版本库与文件操作

1.1 创建版本库

什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

首先在GitBash中cd到要创建仓库的位置(或者直接进入相应目录,点鼠标右键然后选择Git Bash Here),执行git init,仓库创建成功后会在仓库文件夹中生成 .git目录 ,这个目录是Git来跟踪管理版本库的 ,千万不要手贱修改。我们创建Git版本库时,Git会自动为我们创建唯一一个master分支 .

1.2 添加文件到Git仓库

  1. git add <fileName>,将文件放进暂存区stage) ,此命令可反复多次使用,也可同时添加多个文件;
  2. 使用命令git commit -m <message>,添加到版本库 ,即把暂存区的所有内容提交到当前分支 ,其中<message>是本次提交的描述;

1.2.1 查看仓库状态

git status命令可以随时掌握工作区/仓库当前的状态 (显示有变更的文件),此命令的几种结果如下:

  1. Changes not staged for commit:文件更改了,但是还未进入暂存区 ,需要add
  2. Changes to be committed:文件已进入暂存区,但还未提交到版本库,需要commit
  3. Untracked files:表示该文件还从来没有被添加进版本库,这是新添加的文件;

1.2.2 查看修改内容

  如果git status告诉你有文件被修改过,用git diff可以查看修改内容,语法为:git diff <fileName>add文件之前最好看一下。(比较文件的不同,即暂存区和工作区的差异。)

1.2.3 提交修改

   提交修改和提交新文件是一样的两步 :addcommit。可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

1.3 版本回退

   每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。

  1. git log 可以查看提交历史记录(即查看版本库的状态 ),显示从最近到最远的提交日志;git log --pretty=oneline 使每个日志单独成行(简化版输出)。

  2. git中,用HEAD表示当前版本commit id 版本号)。

  3. 回退到上一个版本:git reset --hard HEAD^HEAD^表示回退1个版本,HEAD^^表示回退2个版本,HEAD~100表示回退100个版本。HEAD其实是个指向当前版本的指针。

  4. 返回过去/未来的版本:git reset --hard 新版本的commit id。其中“新版本的commit id”可以只写id号的前几位,Git会自动去找。
  5. git reflog查看历史每一次命令,可以查看每一次提交时的commit id

1.4 工作区和暂存区

  • 工作区:就是当前的工作目录。
  • 版本库:工作区里面隐藏的.git目录(这个不算工作区)就是Git的版本库。

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

  git add + git commit:可以理解为把文件修改添加到暂存区,然后一次性提交暂存区的所有内容到当前分支。 如图:

工作区和暂存区示意图

  注:Git跟踪并管理的是修改,而非文件。 git commit只负责把暂存区的修改提交。每次修改,如果不git add到暂存区,那就不会加入到commit中。

  提交后,用git diff HEAD -- readme.txt命令可以查看工作区版本库里面最新版本的区别 。

补充:

git diff #是工作区(work dict)和暂存区(stage)的比较,比较的是工作区文件与暂存区文件的区别(上次git add后的内容)的区别。

git diff --cached #是暂存区(stage)和分支(master)的比较,比较的是暂存区的文件与仓库分支里(上次git commit后的内容)的区别 。

1.5 撤销修改

  场景1. 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- <file>,这里有两种情况:

  1. 若文件自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
  2. 若文件已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。

  场景2. 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,把暂存区的修改撤销掉(unstage),重新放回工作区 ,回到了场景1。第二步按场景1操作,丢弃工作区的修改即可。

注:git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。

  场景3. 已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退那一节,可以回退到上一个版本,不过前提是你还没有把自己的本地版本库推送到远程,否则就JJ了。

补充:

Unix/Linux 命令中,- 后一般跟短命令选项(通常是单字母,如-m),-- 后一般跟长命令选项。如果只有一个单独的--,后面不紧跟任何选项,则表示命令选项结束,后续的都作为命令的参数而不是选项。例如:

git checkout -- filenamegit checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。)

filename作为git checkout 的参数,而不是选项。

1.6 删除文件

  手动删除或者用命令rm <fileName>删除文件后,执行git add/rm <fileName>git commit-m <message>就可以了。
  另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本git checkout -- file

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

2 远程仓库

  Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。 每个人都从“服务器”仓库上克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
  本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

  1. 创建SSH Key。

      ssh-keygen -t rsa -C "youremail@example.com"    # 一路回车即可,无需设置密码
    

    此时可以在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,这两个就是SSH Key的秘钥对id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

  2. 打开GitHub,在个人主页找到setting,找到SSH and GPG keys,然后,点“New SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容,完后确定添即可。 注:GitHub允许你添加多个Key。

2.1 添加远程库

  让本地和远程仓库同步。在GitHub上新建仓库,此时既可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。

  1. 在本地的learnGit仓库下运行如下命令(先有本地库时,将本地库和远程库关联),此时远程库的名字就是origin

     git remote add origin git@github.com:ft-sunshine/learngit.git      # 需改
    
  2. 把本地库的所有内容推送到远程库上 ,实际上是把当前分支master推送到远程。 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送到远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。 (去掉-u

    git push -u origin master    # 第一次推送
    git push origin master       # 本地提交后,如有必要,可推送本地的最新修改。
    

2.2 从远程库克隆

git clone git@github.com:ft-sunhine/gitskills.git

如果有多个人协作开发,那么每个人各自从远程库克隆一份就可以了。

3 分支管理

  如果你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

3.1 分支与管理

每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支

严格来说HEAD并不是指向提交,而是指向masterHEAD指向当前分支),master(当前分支)才是指向提交的(指向当前分支的提交点)。所以,HEAD指向的就是当前分支,其可以确定当前的分支。 这部分还是推荐看下廖雪峰官网的图,更易理解。

Git分支图

Git分支图

Git鼓励大量使用分支:

  1. 查看分支:git branch

  2. 创建分支(相当于增加了一个dev指针):git branch <name> ,切换分支:git checkout <name>

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

  4. 合并指定分支到当前分支:git merge <name>

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

例子如下:

  • 创建分支dev:git checkout -b dev
  • dev分支上进行一通操作
  • 合并分支 ,先git checkout master切换到主分支,然后执行git merge dev进行合并。然后可以再执行git branch -d dev删除分支

3.2 解决冲突

  合并分支时就可能出现代码冲突,任何合并冲突都必须人去解决。人生不如意之事十之八九,合并分支往往也不是一帆风顺的

  其实冲突的本质是:不同的分支修改了代码相同的部分,从而导致合并分支时出现冲突(虽然冲突,但还是会合并,会自动标注出冲突的地方)。所以解决冲突就需要我们把Git合并失败的文件进行手动修复,改为我们想要的内容再提交add + commit)即可。

合并冲突1

合并冲突2

  可以用带参数的git log查看分支的合并情况(分支合并图): git log --graph --pretty=oneline --abbrev-commit

3.3 分支管理策略

  合并分支时,默认采取的为Fast farword模式,这种合并看不到合并历史,删除分支会丢掉分支信息。

  禁用Fast farword模式时,合并分支时会产生一个新的commit,这样,从分支历史上就可以看出分支信息。 用git merge --no-ff -m "merge with no-ff" dev 命令合并,其中,--no-ff参数,表示禁用Fast forward模式。 因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

$ git log --graph --pretty=oneline --abbrev-commit  // 查看分支历史
*   e1e9c68 (HEAD -> master) merge with no-ff
|\  
| * f52c633 (dev) add merge     //可以看到用--no-ff参数,合并分支时会新创建一次提交
|/  
*   cf810e4 conflict fixed
...

  可以看到,不使用Fast forward模式,merge后就像这样 :
合并分支图

分支策略(分支管理原则)图如下:

分支策略

3.4 Bug分支

  修复bug,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

假设场景是这样的:A为正在开发的软件

  1. 假设master分支上面发布的是A的1.0版本,dev分支上开发的是A的2.0版本,且暂未开发完成。
  2. 若这时用户反映 1.0版本存在漏洞,则需要从dev切换到master去修复漏洞, 这时按理应该先提交在dev分支上的工作,然后从dev分支切换到master分支去修复漏洞,但这时你在dev分支上的工作只进行了一半,还没法提交。
  3. 此时可以用git stash命令来把当前工作现场(dev分支)“储藏”起来,等以后恢复现场后继续工作。
  4. 切换到master分支,在master分支建立issue-101分支(确定要在哪个分支上修复bug,就从哪个分支新建分支),切换到issue-101分支修复漏洞,修复完成后提交,然后切换到master分支上合并issue-101分支git merge --no-ff -m "merged bug fix 101" issue-101
  5. 切换回dev分支,git stash list命令看看stash内容,然后git stash pop,恢复的同时把stash内容也删了继续工作。

注:恢复工作现场的两种方式

  1. 是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除; (你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash:git stash apply stash@{0})。
  2. git stash pop,恢复的同时把stash内容也删了 。

那怎么在dev分支上修复同样的bug?Git专门提供了一个git cherry-pick <commit>命令,让我们能复制一个特定的提交到当前分支。

3.5 强制删除

  开发一个新feature,最好新建一个分支; 如果要丢弃一个没有被合并过的分支(已提交),可以通过git branch -D <name>强行删除。

3.6 多人协作

  因本部分比较重要,所以整理得比较详细,内容略多。

  当你从远程仓库克隆时,实际上Git自动把本地的master分支(或指定的某分支)和远程的master分支(或指定的某分支)对应起来了,并且,远程仓库的默认名称是origin,用git remotegit remote -v可查看远程库的信息。

3.6.1 推送分支

  一般来说,master主分支和dev开发分支,都要时刻与远程库保持同步,所以需要推送。其他分支,比如bug分支和feature分支等,是否需要推动到远程可依具体情况而定。

# 推送时,要指定本地分支,这样,Git就会把该分支(的所有提交)推送到远程库对应的远程分支上
git push origin master  
git push origin dev
3.6.2 抓取分支

  其他小伙伴用git clone xxx从远程库克隆,默认只会克隆master分支,可用git branch查看。若小伙伴也要在dev分支上开发,则必须创建远程origindev分支到本地,用git checkout -b dev origin/dev。完成相关工作后,时不时地把dev分支push到远程,用git push origin dev

  若你的小伙伴对dev分支的某个文件做了修改,并且push了dev分支,而碰巧你也对同样的文件作了修改,并试图推送 git push origin dev,这时会推送失败(出现冲突)。此时应先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送 。

  这时若直接用git pull会失败(其实这里直接git pull origin dev就行了,其实只需要git clone一次后,就建立了本地仓库和远程仓库的链接,以后只需要指定origin就行了),因为到目前为止还没有指定本地dev分支与远程origin/dev分支的链接,应设置devorigin/dev的链接: git branch --set-upstream-to=origin/dev dev,然后再git pull就成功了(git pull是把远程库某分支最新的提交抓下来,然后与本地某分支自动合并)。但这时合并会有冲突,需要手动解决,解决后提交,再git push origin dev即可。

3.6.3 多人协作的工作模式

因此,多人协作的工作模式通常是这样:

  1. 首先,可以试图用git push origin <branch-name>推送自己的修改;
  2. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并
  3. 如果合并有冲突,则解决冲突,并在本地提交;
  4. 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!

如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

3.6.4 小结
  • 查看远程库信息,使用git remote -v
  • 本地新建的分支如果不推送到远程,对其他人就是不可见的;
  • 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
  • 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
  • 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name
  • 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突

问题:A:push 文件1.txt,B:push 文件1.txt(显然冲突),所以先pull,然后手工合并。假如合并过程中,A又push文件1.txt了。等B合并完,push 文件1.txt时,又冲突掉了。感觉这情况很影响工作效率,请问git是否有对这情况有处理机制的?(SVN是有“锁”这概念的)。

答:无解,找A吵一架,所以说共同开发时,合作很重要!

3.7 Rebase

  没看,貌似只是对强迫症患者而设计的,用处也不是很大,暂时没看。廖雪峰这里写的貌似不是很清楚,评论区推荐了两个教程[网址1][https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%8F%98%E5%9F%BA]和[网址2][http://gitbook.liuhui998.com/4_2.html]。

4 标签管理

  Git的标签是版本库的快照,它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动)。总之,tag就是一个让人容易记住的有意义的名字(相比于commit id来说),它跟某个commit绑在一起。

4.1 创建标签

  首先,切换到需要打标签的分支上:

  • 命令git tag <tagname> [commit id]用于新建一个标签,默认标签是打在最新提交的commit上的,也可以指定一个commit id(找到历史提交的commit id:git log --pretty=oneline --abbrev-commit);
  • 命令git tag -a <tagname> -m "describe" [commit id]可以指定标签信息;
  • 命令git tag可以查看所有标签。
  • 可以用git show <tagname>查看标签信息,

注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。

4.2 操作标签

  默认创建的标签都只存储在本地,不会自动推送到远程,所以,打错的标签可以在本地安全删除。 。

  • 命令git push origin <tagname>可以推送一个本地标签到远程库;
  • 命令git push origin --tags可以推送全部未推送过的本地标签到远程库;
  • 命令git tag -d <tagname>可以删除一个本地标签;
  • 命令git push origin :refs/tags/<tagname>可以删除一个远程标签(先从本地删除)。

5 远程仓库的使用

5.1 使用GitHub

  GitHub可以作为免费的远程仓库 ,同时,GitHub是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人的开源项目。

  若想参与别人的开源项目,首先要点“Fork”在自己的账号下克隆一个仓库,然后,从自己的账号下clone(一定要从自己的账号下clone仓库, 否则无法推送修改)。

  • 在GitHub上,可以任意Fork开源仓库;
  • 自己拥有Fork后的仓库的读写权限;
  • 可以推送pull request给官方仓库来贡献代码。

5.2 使用码云

  国内的Git托管服务—码云,码云也提供免费的Git仓库,5人以下小团队免费。码云的基本操作和GitHub的操作一致。

  把本地库关联到远程库:(假设已经有了一个本地库叫“learngit ”)

  1. 首先,在码云上创建一个新的项目,项目名称最好与本地库保持一致 。

  2. 然后,我们在本地库上使用命令git remote add <URL>把它和码云的远程库关联。若这时出现远程库origin已存在的错误,则应该先删除远程库:git remote rm origin

  3. 这时载再关联码云的远程库即可成功,可用git remote -v查看,这时就可以通过git push命令把本地库推送到Gitee上。

  4. 一个本地库能既关联GitHub,又关联码云(注:git给远程库起的默认名称是origin) :

    • 先删除已关联的名为origin的远程库:git remote rm origin

    • git remote add github git@github.com:michaelliao/learngit.git

    • git remote add gitee git@gitee.com:liaoxuefeng/learngit.git

      注意此时远程库的名称叫gitee,不叫origin ,可用git remote -v查看。

    • 此时推送的命令变为:git push github mastergit push gitee master

6 自定义Git

  自定义Git包括三节:1.忽略特殊文件 2.配置别名 3. 搭建Git服务器。其中,其中忽略特殊文件较为常用,这里不再赘述,直接浏览[廖神网站][https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137621280731812dec22ecc9b44f4b2ca1c680f181a5b000]即可。

常见问题及解决办法

  • 每次push,pull都需要密码

    // 这个命令则是在你的本地生成一个账号密码的本子似的东东,这样就不用每次都输入了(但是还得输入一次)

    git config --global credential.helper store

    // 这个指令对于windows,linux都是通用的,可以通过以下命令查看

    cat ~/.git-credentials

链接

  • 48
    点赞
  • 287
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值