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指针

git&github_第1张图片

3 git常用命令

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

    #这个命令,会在"~/.gitconfig"文件中添加信息
    #--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置
    git config --global user.name "Your Name"
    git config --global user.email "[email protected]"
    
  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 团队内部合作

git&github_第2张图片

5.2 跨团队合作

git&github_第3张图片

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 "[email protected]"
    #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 [email protected]:michaelliao/gitskills.git
#查看远程库信息
git remote
#查看远程库详细信息,如果没有推送权限,就看不到push的地址
#origin  [email protected]:michaelliao/learngit.git (fetch)
#origin  [email protected]: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 [email protected]: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

    git&github_第4张图片

  2. 初始化本地仓库

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

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

    git&github_第5张图片

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

    git&github_第6张图片

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

    git&github_第7张图片

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

    git&github_第8张图片

    git&github_第9张图片

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

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

    git&github_第10张图片

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

    git&github_第11张图片

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

    git&github_第12张图片

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

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

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

你可能感兴趣的:(日常工作总结)