git&github

1 git简介

  1. git为分布式版本控制系统,svn是集中式版本控制系统
  2. 集中式
    1. 版本库存放在中央服务器,干活前,用自己电脑先从中央服务器取得最新的版本,干完活后,再把最新文件推送给中央服务器。下载时,只下载最新版
    2. 更新后,svn存储的是两个版本之间的差异,需要从版本n回滚到版本1时,必须先从版本n回滚到版本n-1,依次类推,直到回滚到版本1,效率非常低
  3. 分布式
    1. 没有中央服务器,每个人的电脑上都是一个完整的版本库,也就是存放了当前版本代码的同时,还存放了历史版本,以及历史版本的索引,因此每个人的电脑都可以作为git的服务端
    2. 当你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。但在实际使用分布式版本控制系统时,其实很少在两人之间的电脑上推送版本库的修改,因为可能两人不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已
    3. 需要从版本n回滚到版本1时,只需要移动指针到版本1的索引处即可,效率非常高

2 git中的几个重要概念

  1. 工作区:你在电脑里能看到的目录,也就是写代码的地方
  2. 本地库:本地当前使用的版本库,暂存区的文件,执行git commit后进入本地库
  3. 版本库:工作区中一个隐藏的".git"文件就是Git的版本库,版本库中包含以下重要内容
    1. 暂存区(stage):工作区的文件,执行git add后,进入暂存区
    2. Git自动创建的master分支,以及指向master分支的HEAD指针

在这里插入图片描述

3 git常用命令

  1. 因为Git是分布式版本控制系统,所以,每个机器提交时都必须自报家门,可以使用如下命令设置你的名字和Email地址

    #这个命令,会在"~/.gitconfig"文件中添加信息
    #--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置
    git config --global user.name "Your Name"
    git config --global user.email "email@example.com"
    
  2. 版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来

    #将当前目录变成Git可以管理的仓库,命令执行后,当前目录下多了一个.git隐藏文件
    git init
    
  3. 将文件添加到暂存区

    git add 文件名
    
  4. 将暂存区所有文件提交到当前分支

    #如果不执行git add,而直接执行git commit,那么修改内容不会被提交。也就是说git commit只负责把暂存区的修改提交到本地库
    git commit -m "本次提交的说明"
    #同时完成git add和git commit两个操作
    git commit -am README.md
    
  5. 从近到远显示提交日志

    #1. 由近到远记录了commit id、作者、提交时间、提交摘要等内容
    #2. commit id相当于一个索引key,通过这个索引可以找到历史记录对应的具体内容
    #3. 当历史记录过多,一页装不下,会分页,最后一行显示":",此时点击空格,翻到下一页,按b,翻到上一页,按q退出,如果到尾页,会显示"END"
    git log
    #4. 当条数过多后,查看比较费劲,可以将日志信息格式化后展示,此处表示将每次提交的信息,只用一行展示
    git log --pretty=oneline
    #5. 一行展示,且只保留commit id的后七位
    git log --oneline
    #6. git log命令无法查看当前版本之后的commit id信息,这就导致如果通过git reset命令恢复到历史某个版本后,git log无法再查看其之后版本的信息
    #7. 而git reflog命令可以,且提供了commit id的后七位与HEAD@{数字}的对照关系,数字表示回到对应commit id的历史版本需要几步
    git reflog
    
  6. 还原到指定版本

    #1. HEAD指向当前分支master的最后一次提交
    #2. HEAD^指向当前分支master的上一次提交
    #3. HEAD^^表示上两个,HEAD~100表示上100个
    #4. hard参数表示,当本地库指针移动后,强制重制暂存区和工作区,防止他们之间不一致,一般只用hard不用mixed和soft
    git reset --hard 67c8975
    git reset --hard HEAD^
    git reset --hard HEAD~100
    #5. mixed:本地库指针移动后、重置暂存区,但工作区代码不变
    git reset --mixed 67c8975
    #6. soft:本地库指针移动后,暂存区、工作区都不发生变化
    git reset --mixed 67c8975
    
  7. 比较工作区、暂存区、指定版本

    #1. git是以行为单位管理变更的,当修改某行数据时,都是先删除该行,再重新添加一行,diff命令查出的内容中"-"就表示删除的行,"+"就表示新增的行
    #1. 比较工作区与暂存区
    git diff
    #2. 比较指定文件
    git diff 文件名
    #3. 比较工作区与指定版本(已commit中内容)
    git diff HEAD/${commit id}
    #4. 比较暂存区与指定版本(已commit中内容)
    git diff --cached HEAD/${commit id}
    
  8. 撤销工作区的修改

    1. 如果文件自修改后还没有被放到暂存区,会将该文件撤销到和最新版本库中内容相同,此时和git reset --hard作用相同
    2. 如果文件已被放到暂存区后又做了修改,会将该文件撤销到放到暂存区后的状态
    #如果不加"--"",就变成了"切换到另一个分支"的命令
    git checkout -- readme.txt
    
  9. 从版本库中删除文件

    #1. 先在工作区删除,如果此步骤为误删,可以使用上面介绍的git checkout -- readme.txt恢复工作区内容
    rm test.txt
    #2. 在暂存区中提交删除,此处使用git add test.txt也可以
    git rm test.txt
    #3. 提交到版本库
    git commit -m "remove test.txt"
    
  10. 查工作目录和暂存区的状态,和git log区别在于,后者用于查看commit的信息,前者用于查看当前目录与最新版本的区别,以及暂存区与最新版本的区别

    git status
    

4 代码托管中心

  1. 我们通常使用代码托管中心来维护远程库
  2. 局域网环境:搭建gitlab作为代码托管中心,需要自己搭建
  3. 外网环境:使用github或gitee作为代码托管中心,不需要自己搭建

5 远程库与本地库交互方式

5.1 团队内部合作

在这里插入图片描述

5.2 跨团队合作

在这里插入图片描述

5.3 相关命令说明
  1. push:git操作,将本地仓库更新内容提交给远程库
  2. clone:git操作,将远程库中内容,拷贝一份到自己本地,并初始化本地库。如果克隆的是他人的仓库,由于他人并没有邀请你加入团队,因此你无法向他人仓库中push代码,只能pull
  3. pull:git操作,使用远程库中内容更新本地库
  4. fork:github操作,将别人仓库,拷一份到自己的github中
  5. pull request:github操作,将自己github中更新的内容,提交给他人的github,他人同意后,他人的github仓库中内容才会被更新。在github上项目的Pull requests标签中,能够查看到是谁请求的pull request,以及申请的备注信息等,其内Files changed中还能看到本次pull request所更新的具体内容,如果没有问题就可以通过merge pull request来同意pull request的申请
  6. fetch:git操作,pull=fetch+merge,一般都使用pull。会创建并更新origin/master分支,并将远程库中代码拉取到这个新分支中,此操作不会自动更新到工作区中,fetch后,可以通过git checkout origin/master命令查看新创建的这个分支,是否和远程库中内容一致,之后执行merge操作将origin/mater分支与master分支进行合并。

6 github使用

6.1 在github上创建账户
6.2 设置 SSH Key
  1. 使用https的url或ssh的url都可以将远程项目克隆到本地

  2. 使用https克隆时,每次push操作都需要重新输入github用户名和密码(windows10下可能会记录用户名和密码,不必每次输入)

  3. 使用ssh克隆时,push操作不需要输入github用户名与密码,但使用ssh克隆时,需要在克隆之前先配置和添加好ssh key,而只有项目拥有者本人才能添加ssh key

  4. 可以先使用自己电脑创建ssh key公钥和私钥,然后将公钥告诉给github,这样,就可以在自己的电脑上,通过ssh协议,使用私钥来访问github的服务器了

6.2.1 设置流程
  1. 本机创建创建一个 SSH key

    #-t 指定密钥类型,默认是 rsa ,可以省略。
    #-C 设置注释文字,比如邮箱。
    #-f 指定密钥文件存储文件名,默认文件名为id_rsa(私有密钥)和id_rsa.pub(公开密钥)
    #邮箱为注册github使用的邮箱
    ssh-keygen -t rsa -C "your_email@example.com"
    #Generating public/private rsa key pair.
    #Enter file in which to save the key
    #(/Users/your_user_directory/.ssh/id_rsa):
    #按回车键
    #Enter passphrase (empty for no passphrase):
    #输入push文件的时候要输入的密码,可以不输密码直接回车
    #Enter same passphrase again:
    #再次输入密码
    
  2. github上添加公开密钥,今后就可以用私有密钥进行认证了,在SSH Keys中粘贴 id_rsa.pub 文件里的内容

    cat ~/.ssh/id_rsa.pub
    
  3. 修改私钥密码

    cd ~/.ssh
    #修改私钥,执行命令后提示输入密码,两次都直接回车就可以去掉密码,去掉密码后,git push就不再需要输入密码
    ssh-keygen -p -f id_rsa
    
6.3 在github上创建仓库

Create repository

6.4 从远程仓库克隆到本地
#1. 此处也可以使用https协议克隆
#2. 克隆后,git会自动把本地的master分支和远程的master分支对应起来了,且为远程仓库创建别名,别名默认为origin
#3. A克隆了B的远程库后,是没有push权限的,需要由B邀请A才能拥有权限,具体流程为,B进入github--Settings--Manage access--输入要A的github账号--复制邀请链接,然后B将该邀请链接发送给A,A在浏览器中输入该邀请链接后接受邀请,之后A就获取了push权限
git clone git@github.com:michaelliao/gitskills.git
#查看远程库信息
git remote
#查看远程库详细信息,如果没有推送权限,就看不到push的地址
#origin  git@github.com:michaelliao/learngit.git (fetch)
#origin  git@github.com:michaelliao/learngit.git (push)
git remote -v
#删除远程库
git remote rm origin
6.5 如果已经存在本地仓库,也可以额为本地库添加远程仓库
#1. 创建本地库
#2. 在github上创建仓库
#3. 在本地创建远程库地址的别名,origin为别名,可以人为指定
	#1. 注意michaelliao必须是自己的仓库,如果是别人的,虽然能加上,但push不上去,因为你的SSH Key公钥不在他人的账户列表中
git remote add origin git@github.com:michaelliao/learngit.git
#4. 将本地库中master分支推送到远程库origin上,这样,二者就建立起了联系
git push origin master
#5. 拉取也可以建立联系
git pull origin master

7 分支

7.1 分支简介
  1. 版本控制过程中,可以使用多条线同时推进多个任务,这里面说的多条线就是多个分支。每当需要新开发一个独立功能时,为了防止新功能对原功能有影响,通常开辟一个新分支

  2. 分支的好处:同时多个分支可以并行开发,互不耽误,互不影响,提高开发效率,如果有一个分支功能开发失败,直接删除该分支即可,不会对其他分支产生任何影响

  3. 每次提交,git都把它们串成一条时间线,这条时间线就是一个分支。之前的操作中,只有一条时间线,在git里,这个分支叫主分支,即master分支

  4. 一开始的时候,master分支是一条线,master指向最新的提交,HEAD指向master,这样就能确定当前分支,以及当前分支的提交点

111

  1. 每次提交,当前分支都会向前移动一步,随着在master上不断提交,master分支的线也越来越长
  2. 当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上

git-br-create

  1. Git创建一个分支非常快,因为只需增加一个dev指针,并且修改HEAD的指向,工作区的文件都没有任何变化
  2. 从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而mater指针不变

git-br-dev-fd

  1. 假如我们在dev上的工作完成了,就可以把dev合并到master上,Git通过把master指向dev的当前提交,就完成了合并

git-br-ff-merge

  1. 所以Git合并分支也很快,就改改指针,工作区内容也不变
  2. 合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支

git-br-rm

7.2 分支的最佳实践
  1. 创建、合并和删除分支非常快,所以git鼓励你使用分支完成某个任务,合并后再删掉分支
  2. 这样做和直接在master分支上工作效果一样,但过程更安全
  3. 添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个分支,在上面开发,完成后,合并,最后,删除该feature分支
7.3 分支操作
  1. 查看分支

    #查看分支名称、最后一次commit id、摘要,*表示当前所在分支
    git branch -v
    
  2. 创建与切换分支

    #1. 创建分支feature-A
    git branch feature-A
    #2. 切换到feature-A分支
    	#1. 切换到新分支后,通过git add、git commit就会在新分支上提交更新
    	#2. 在A分支修改文件并提交后,切换为原来的master分支后,是看不到修改内容
    git checkout feature-A
    #3. 创建并切换到feature-A分支
    git checkout -b feature-A
    #4. 快速切回到上一个分支
    git checkout - 
    #5. 由于git checkout和上面撤销工作区的修改命令重复,因此最新版本的Git提供了新的git switch命令来切换分支
    #切换分支
    git swtich dev
    #创建并切换分支
    git switch -c dev
    
  3. 删除分支

    #5. 删除分支
    git branch -d feature-vulcan
    #6. 强行删除未被合并过的分支
    git branch -D feature-vulcan
    
  4. 合并两个分支

    #1. 现要将dev分支合并到master分支上,需要先切换回master分支
    git checkout master
    #2. 将dev合并到master上
    git merge dev
    
  5. –no-ff合并分支

    1. 假设当前分支信息如下

                A---B---C feature
               /
      D---E---F master
      
    2. 执行git merge feature命令时,只会简单地把指针右移,叫做"快进"(fast-forward),合并后结果如下

                A---B---C feature
               /          master
      D---E---F 
      
    3. 而如果使用git merge --no-ff feature命令禁止快进式合并,合并后结果如下,也就是会产生一个新的提交

                A---B---C feature
               /         \
      D---E---F-----------G master
      
    4. 快进式合并会把feature的提交历史混入到master中,搅乱master的提交历史。但如果你根本不在意提交历史,也不爱管 master 干不干净,那么 --no-ff 其实没什么用。不过,如果某一次 master 出现了问题,你需要回退到上个版本的时候,比如上例,你就会发现退一个版本到了 B,而不是想要的 F,因为 feature 的历史合并进了 master 里

  6. 图表形式查看分支的合并情况

    git log --graph
    
  7. 与远程库中分支建立关联:可以将远程库中的某个分支设为本地仓库中的某个分支的上游,这样之后,git pushgit pull命令就不需要再加参数,默认会向当前分支的上游分支去进行pushpull

    #1. 方案一:push的同时添加上游分支,比较常用,且如果远程库中当前没有master分支,就必须使用这个命令,为远程库建立分支的同时,设定上有游分支
    git push -u origin master
    #2. 克隆后,默认情况下本地只有master分支,如果需要其他分支,需要创建远程origin的dev分支到本地
    git checkout -b dev origin/dev
    #3. 方案二:直接与远程服务器上的dev进行关联
    git branch --set-upstream-to=origin/dev dev
    

8 git冲突解决

  1. 不同分支,对同一文件,同一位置,进行了修改与提交,当想进行merge操作时,就会产生冲突

    #1. 由于当前master分支和feature1分支都修改了readme.txt文件的同一位置,尝试将feature1合并到master上时,提示Merge conflict in readme.txt,产生冲突
    git merge feature1
    #2. 查看冲突的文件
    git status
    #3. 冲突文件中,两个分支的文件中间由==========隔开,需要人为修改冲突文件,决定保留哪部分内容,之后将冲突文件add、commit
    

    git-br-feature1

    git-br-conflict-merged

  2. 当向远程库中push代码时,也可能会产生冲突,此时就需要先从远程库pull下来最新内容,此时就获取到了冲突文件,对冲突文件修改后(冲突解决方式和本地一样),再push即可

9 git stash

  1. 如果再当前的feature-A做了修改,且当前修改内容与master最新版本中内容冲突,此时是无法切换到master分支,会报错

  2. 但如果此时急需切换回master分支,解决一个致命的bug,此时可以使用git stash把当前分支的"工作现场""储藏"起来,等以后bug解决后,再恢复"工作现场"并继续工作

  3. git stash储藏的内容可以为任何分支使用,保存的内容包括工作区与暂存区新增的内容

  4. 执行git stash后,git status查看工作区与暂存区,会发现没有任何内容,表示当前工作区、暂存区,和上一版本没有任何区别

    #1. stash命令可以执行多次,下面命令可以查看stash储藏的所有历史内容
    git stash list
    #2. 恢复
    git stash apply
    #3. 删除
    git stash drop
    #4. 恢复并删除
    git stash pop
    #5. 恢复到指定的某次stash,stash@{0}为git stash list中查出的stash版本号
    git stash apply stash@{0}
    
  5. 解决完master上的bug后,切回到feature-A,并使用git stash恢复了feature-A,但此时feature-A内容是从master来的,它其实也存在着master中修复的那个bug,该bug在feature-A中尚未被修复,可以使用git cherry-pick 4c805e2复制一个特定的提交到当前分支,要注意这次提交的hash值,和修复bug时提交的hash值不同,这两个commit只是改动的内容相同,但是两个不同的commit

10 标签

  1. 标签是打在提交上的

  2. 打标签

    #1. 为HEAD指向的当前分支的当前版本打标签
    git tag v1.0
    #2. 为指定commit id内容打标签
    #a. 先找到历史的commit的id
    git log --pretty=oneline --abbrev-commit
    #b. 对id值为f52c633的commit打标签
    git tag v0.9 f52c633
    #3. 创建带有说明的标签,-a指定标签名,-m指定说明文字
    git tag -a v0.1 -m "version 0.1 released" 1094adb
    
  3. 查看标签

    #1. 查看所有标签,标签内容按字母排序,而不是时间
    git tag
    #2. 查看打了指定标签的提交
    git show v0.9
    
  4. 删除标签

    git tag -d v0.1
    
  5. 默认情况下,标签信息都只存储在本地,不会自动推送到远程,可以使用命令将标签推送到远程

    git push origin v1.0
    #一次性推送全部尚未推送到远程的本地标签
    git push origin --tags
    
  6. 删除标签

    #如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除
    git tag -d v0.9
    #然后,从远程删除
    git push origin :refs/tags/v0.9
    

11 git深入学习

  1. 官方推荐书籍:http://git-scm.com/book/zh/v1

12 忽略特殊文件

  1. 有时某些文件会被放到git工作目录中,但又不想提交它们,比如保存了数据库密码的配置文件、UE修改后保留的备份文件等

  2. 每次git status都会显示Untracked files,影响使用

  3. 可以编辑.gitignore文件,从而让git不对这些文件进行管理

    # Windows:
    Thumbs.db
    ehthumbs.db
    Desktop.ini
    # Python:
    *.py[cod]
    *.so
    *.egg
    *.egg-info
    dist
    build
    # My configurations:
    db.ini
    deploy_key_rsa
    
  4. .gitignore文件也可以交给git管理

  5. 如果git add无法添加某个文件到暂存区,可能是这个文件被.gitignore忽略了,如果你确实想添加该文件,可以使用-f强制添加

  6. 如果你觉得不应该忽略该文件,是.gitignore文件写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore -v App.class检查是文件中哪行导致了App.class文件被git忽略

13 source tree

  1. git的图形化界面,和git关系类似tortorise svn和svn的关系,同样比较优秀的git图形化界面还有fork

14 idea集成git

  1. 配置git

    在这里插入图片描述

  2. 初始化本地仓库

    在这里插入图片描述

  3. 将当前项目初始化为本地仓库后,项目中新建文件时会提示是否进行git add操作,项目中,执行了git add后的文件名是绿色,未执行git add操作的文件名是红色,git commit后文件名变为白色

  4. 可以手动addcommit文件和目录

    在这里插入图片描述

  5. git边栏中,console标签就是之前git命令执行的日志、log就是git log的内容

    在这里插入图片描述

  6. 当在文件中编写新代码时,和本地库代码不一致的位置,前面会出现绿条

    在这里插入图片描述

  7. 可以在源码上或提交时查看与本地库代码内容对比

    在这里插入图片描述

    在这里插入图片描述

  8. 由于本地库和远程库之间,各自记录的起点终点完全不同,因此git pull或通过idea直接拉取代码会失败,所以先手工建立关联,使用--allow-unrelated-histories参数,表示"允许忽略不相关的历史信息"地拉取

    #拉取远程库数据
    git pull git@github.com:handidiao/git-tutorial.git master --allow-unrelated-histories
    #add commit拉取过来的数据
    #将本地数据推送到远程库
    git push -u git@github.com:handidiao/git-tutorial.git master -f
    
  9. 通过idea,add、commit后,就可以推送项目到远程仓库了

    在这里插入图片描述

    在这里插入图片描述

  10. 也可以commit的同时,push到远程仓库

    在这里插入图片描述

  11. 当push到远程库时,如果有冲突,会提示如下信息,此时点击merge

    在这里插入图片描述

  12. 此时提示如下信息,提示可以选择用自己的或者用远程库中内容,又或者进行合并,此处选择Merge

    在这里插入图片描述

  13. 左侧为你的代码,中间为你修改之前代码,右侧为远程库中代码,此时可以将中间部分代码修改为你最后需要的代码,点击apply即可,此时本地库和工作空间代码已经被修改为最新,再次通过idea进行push即可最终解决冲突

    在这里插入图片描述

  14. 通过克隆远程仓库方式创建项目

    在这里插入图片描述

    在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值