• git.md


    Git 使用

    诞生

    1. BitMover公司收回Linux社区对BitKeeper的免费使用权。

    2. Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了

    分布式

    • 集中式版本控制系统:版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
    • 分布式版本控制系统: 没有“中央服务器”,每个人的电脑上都是一个完整的版本库。分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

    创建版本库(respository)

    mkdir learngit
    cd learngit
    git init      
    

    之后,会多出.git目录

    git add .  # 将 . 文件夹添加到仓库
    git commit # 提交至仓库
    

    时光机穿梭

    • 当前状态:git status

    • 查看更改具体内容: git diff

    版本回退

    commit之后,相当于一个快照

    • 查看commit历史: git log

      查看简略日志: git log --pretty=oneline

      当前版本用HEAD表示

    • 版本回退: git reset --hard HEAD^ # HEAD^表示当前版本的前一个版本

      再次返回当前版本,找到SHA1值

      git reset --hard 70131

      • 查找SHA1值:

        git reflog # reference logs

    Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向改变,再把工作区的文件更新

    工作区(Working Directory)

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

    版本库(Repository)

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

    git add实际就是把文件修改添加到暂存区stage

    git commit实际是将stage提交到当前分支master

    管理修改

    Git跟踪并管理的是修改,而非文件。

    git diff HEAD 命令可以查看工作区和版本库里面最新版本的区别

    撤销修改

    1. 还未提交到暂存区

      最新的git合并了checkout和reset

      原来的git checkout 可以使用 git restore 代替

      原来的git reset HEAD 可以使用 git restore --staged 代替

    git checkout -- readme.txt

    命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

    一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

    一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

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

    git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。

    1. 已经提交到暂存区

      git restore --staged index.htmlgit reset HEAD index.html

    2. 已经提交到版本库

      进行版本回退

    删除文件

    1. 添加新文件

      touch 1.txt && git add 1.txt

    2. 从版本库中删除该文件: git rm test.txt

    git rm file并且git commit并不是删除了版本库里的某个版本号,而是对工作目录下的删除操作进行了一个记录,会在仓库里生成一个新的版本号,在该版本下没有该文件。但是可以用git reset --hard commit_id进行版本回退,回退到有这个文件的版本号。而git checkout commit_id file命令是从含有该文件的旧版本号里把该文件拿出来,放到现版本里,版本号不改变。

    远程管理

    1. 在github上新建仓库

    2. git remote add origin git@github.com:michaelliao/learngit.git

    3. git push -u origin master,将本地的master分支推送到远程origin

      由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

    4. 之后提交:git push origin master

    5. 下载:git clone git://XXXXXXXXXX

    分支管理

    创建与合并分支

    HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

    git-br-initial

    当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:git-br-create

    从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

    git-br-dev-fd

    假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

    git-br-ff-merge

    所以Git合并分支也很快!就改改指针,工作区内容也不变!

    合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

    git-br-rm

    # 创建 dev 分支同时切换至dev, -b == branch + checkout
    git checkout -b dev 
    # 或者
    git switch -c dev
    # 查看当前分支
    git branch
    # 切换分支
    git checkout dev 
    # 或者
    git switch dev
    # 合并分支
    git merge dev
    # 删除分支
    git branch -d dev
    

    解决冲突

    1. 创建新分支feature

      git switch -c feature1

    2. 在新分支上修改:

      git add . && git commit -m 'modified something'

    3. 切换master分支

      git switch master

    4. 修改文件:

      git add . && git commit -m 'modified other somthing'

    现在,master分支和feature1分支各自都分别有新的提交,变成了这样:

    git-br-feature1

    这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:

    $ git merge feature1
    Auto-merging readme.txt
    CONFLICT (content): Merge conflict in readme.txt
    Automatic merge failed; fix conflicts and then commit the result.
    

    现在,master分支和feature1分支变成了下图所示:

    git-br-conflict-merged

    删除feature1分支:$ git branch -d feature1

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

    分支策略

    在实际开发中,我们应该按照几个基本原则进行分支管理:

    首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

    那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

    你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

    所以,团队合作的分支看起来就像这样:

    git-br-policy

    合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

    Bug分支

    stash可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:git stash

    查看:git stash list

    恢复:git stash apply && git stash drop git stash pop

    Git专门提供了一个cherry-pick命令,让我们能复制一个特定的提交到当前分支:

    $ git branch
    * dev
      master
    $ git cherry-pick 4c805e2
    [master 1d4b803] fix bug 101
     1 file changed, 1 insertion(+), 1 deletion(-)
    

    修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

    当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;

    在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick 命令,把bug提交的修改“复制”到当前分支,避免重复劳动

    Feature分支

    git switch -c feature-vulcan
    git add vulcan.py
    git status
    git commit -m "add feature vulcan"
    
    git switch dev
    
    # 强制删除 feature-vulcan
    git branch -D feature-vulcan
    

    如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除。

    多人协作


    当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin

    • 查看远程库的信息:git remotegit remote -v

    • 推送分支: git push origin master

      git push origin dev

    推送:

    • master分支是主分支,因此要时刻与远程同步;
    • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
    • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
    • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

    你的小伙伴要在dev分支上开发,就必须创建远程origindev分支到本地,于是他用这个命令创建本地dev分支:

    $ git checkout -b dev origin/dev
    

    碰巧你也对同样的文件作了修改,并试图推送:

    $ cat env.txt
    env
    
    $ git add env.txt
    
    $ git commit -m "add new env"
    [dev 7bd91f1] add new env
     1 file changed, 1 insertion(+)
     create mode 100644 env.txt
    
    $ git push origin dev
    To github.com:michaelliao/learngit.git
     ! [rejected]        dev -> dev (non-fast-forward)
    error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    解决:Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:

    git pull  # 失败,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接
    git branch --set-upstream-to=origin/dev dev
    git pull
    
    # 解决冲突
    git push origin dev
    

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

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

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

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

    Rebase

    标签管理

    发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。按照tag v1.2查找commit就行

    创建标签

    1. 切换需要标签的分支:git branch git checkout master

    2. 打标签:git tag v1.0

    3. 查看:git tag

    4. git tag v0.9 f7d08jjd

    5. 查看标签信息:git show <tagname>

    6. 还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:

      $ git tag -a v0.1 -m "version 0.1 released" 1094adb
      

    操作标签

    • 删除标签: git tag -d v0.1

    • 推送标签到远程:git push origin v1.0

      一次性推送某个标签到远程:git push origin --tags

    • 删除远程标签:

      1. 删除本地标签:git tag -d v0.9
      2. 删除远程标签:git push origin :refs/tags/v0.9

    使用Github,Gitee

    自定义Git

    .gitignore

    忽略文件的原则是:

    1. 忽略操作系统自动生成的文件,比如缩略图等;
    2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
    3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

    git check-ignore命令检查.gitignore

    配置别名

     git config --global alias.st status
    

    Git Cheat Sheet

    Git Cheat Sheet

    Git

    .gitnore	# 忽略文件列表
    git init
    	status
    	add filename
    	diff
    	reset
    	config
    		--global user.name "XXXXX"
    		--global user.email "XXXX"
    	commit -m "XXXXXXX"
    	rm --cached filename	# 不再追踪
    	brach XXX			# add 分支
    	checkout XXX	# 转换到某个分支
    	merge	XXX 	#合并
    	brach 	-d  XXX	
    			-D XXX	# 强制删除
    	remote add origin XXX #远程推送
    	push --set-upstream 	
    	log 	[--prettty=oneline]
    	
    # 回退
    	|-----|--add--|-----|--commit--|-----|
    time  1		2		3 		4			5
    	
        1. 手动删除修改 
        	git checkout --file filename
        3.  git reset HEAD filename 
        	git checkout --file filename
    	5. 回退版本
    	
    # 恢复
    git checkout --filename
    
    git remote add origin "address"
    	push -u origin master
    	push orign master
    	
    

  • 相关阅读:
    【php】 mac php-redis install
    【php】phpstorm 配置远程调试
    【cookie】cookie探讨
    第一篇文章
    SQL经典50查询语句案例_1(查询“001”课程比“002”课程成绩高的所有学生的学号)
    SQL经典50查询语句案例_10(查询没有学全所有课的同学的学号、姓名)
    SQL经典50查询语句案例_9(查询所有课程成绩小于60分的同学的学号、姓名)
    SQL经典50查询语句案例_8(查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名)
    SQL经典50查询语句案例_7(查询学过“叶平”老师所教的所有课的同学的学号、姓名)
    SQL经典50查询语句案例_6(查询学过“001”并且也学过编号“002”课程的同学的学号、姓名)
  • 原文地址:https://www.cnblogs.com/nsfoxer/p/16321409.html
Copyright © 2020-2023  润新知