git 从入门到崩溃

https://git-scm.com/book/en/v2


# Git 是分布式版本控制工具,存储版本控制信息时使用自定义的一套文件系统存储机制
# Git 中所有数据在存储前都计算SHA-1校验和,然后以校验和来引用 (此功能构建在其底层)
# 工作区有隐藏的.git目录作为版本库存在,它不属于工作区
# 版本库里存了很多东西,其中最重要的是名为 stage (或称index) 的暂存区
# 还有自动创建的第一个分支master及指向master头部的指针: HEAD

# ----------------------------------------

# 工作区 -->  暂存区 --> 版本库 --> 远程仓库 

# 文件的三种状态(按顺序)
# 1. 已修改 modified:    尚未add到Index
# 2. 已暂存 staged:      将修改添加到了暂存区,但未提交到本地版本库
# 3. 已提交 committed:   已经写入到了本地版本库中

# ---------------------------------------- HEAD 与 Index

HEAD
# 是当前分支最顶端的别名,指向最新的提交
# 上个版本就是HEAD^,上上个版本就是HEAD^^,往前100个版本写100个^比较麻烦,也可写成 HEAD~100

Index
# 暂存区是一系列将被提交到本地仓库的文件集合(该集合将会成为提交后HEAD指向的那个commit对象)
# 它是文件,保存了下次将要提交的文件列表信息,通常称为索引或暂存区

git 从入门到崩溃_第1张图片
git 从入门到崩溃_第2张图片

初始化


# 生成SSH密钥对
ssh-keygen -t rsa -C "[email protected]"

# 初始化当前目录以生成本地版本库 (建立服务端形式无工作区裸仓库: git init --bare workspace.git)
# 注: 执行init后不能在当前目录执行git clone,但可执行 git remote add Name Repo_url ...
# 注: 该操作将在当前路径下创建名为 .git 的子目录
git init .

# -------------------------------------------- git config

# 环境设置
#   --system  基于系统的全局,相关配置位于 /etc/gitconfig
#   --global  基于用户的全局,相关配置位于 ~/.gitconfig 或 ~/.config/git/config
#   --local   仅针对当前项目,相关配置位于当前项目的 .git/conf (优先级最高)

git config --local user.name  "bluevitality"                # 用户信息
git config --local user.email "[email protected]"         # 用户邮箱
git config --local core.editor vim                          # 默认编辑器
git config --local merge.tool  vimdiff                      # 差异分析工具
git config --local alias.st status                          # 使用别名代替命令
git config --local alias.last 'log -1'                      # 最新的提交信息
git config --list [--global|--system|--local]               # 查看配置信息

# 跳过命令方式对特定作用范围的配置文件进行编辑
# git config -e [--global|--system|--local]

# -------------------------------------------- 

# 添加本地仓库与远程仓库的关联(此处使用origin指代远程服务器的URL,提交时只需使用该名称即可)
git remote add origin git://github.com/someone/another_project.git

Example


# 克隆远程仓库到本地的 ./Bluevitality 目录下 (这是较为简单的初始化方式)
# 默认配置下远程仓库的每个版本都将被克隆过来
git clone [email protected]/bluevitality/Bluevitality.git [./Bluevitality]

# ----------------------------------------------------------- git pull

# 拉取当前分支所跟踪的服务器分支,从服务器抓取后将该远程分支合并入当前分支
git pull

# 将名为origin的版本库的代码更新到本地master分支 (pull指令包含了fetch指令的所有操作)
# 这相当于 git fetch 和 git merge (实际工作中fetch更好,因为在merge前可查看差异情况)
git pull origin master

# ----------------------------------------------------------- git add

# 将工作区改变的对象添加到暂存区
# 将当前更改或新增的文件加入到暂存区,加入到暂存区就表示开始记入了版本历史 ...
# 其参数 -A 包括了删除对象的操作 (默认仅添加修改或新增的对象)
git add <Filename|.|*|-A>

# 对文件改名 (相当于 mv old new && git add new)
git mv OLDNAME NEWNAME 

# ----------------------------------------------------------- git rm
 
# 删除工作区文件并将这次删除放入暂存区(若要删除已提交到暂存区的文件则需添加 -f)
git rm filename [-f]

# 停止暂存区中对特定文件的追踪但不从工作区删除,即 "untage" (从暂存区删除)
# 并且将这次删除的操作放入暂存区,此时若提交则版本库中的这个文件也会消失 ...
git rm filename --cached

# ----------------------------------------------------------- git commit

# 只有当使用 add 添加到暂存区后再 commit 才会被提交到版本库(只把暂存区的修改提交到仓库)
# 否则需使用 -a 参数将 add与commit 合并执行并提交到本地仓库(直接提交修改而不经过暂存区)
git commit -a -m "commit info.."
   
# 将当前暂存区要提交的信息与上次的提交信息合并(若暂存区未发生改变则相当于重写上次的提交信息)
git commit --amend -m "提交合并"


# ----------------------------------------------------------- git checkout [option] [object]

# 查看工作区与暂存区之间的状态 (携带 -s 参数将得到紧凑格式的输出)
git status [-s]

# checkout有两个作用:
# 1.在不同的分支之间切换,如 'git checkout BRANCH'
# 2.还原代码,如 'git checkout app/model/user.rb' (将该文件从上个已提交版本中回滚)

# 让文件回退至最近一次 commit/add 后的状态 ( 参数 -- 很重要,没有它就变成了切到其他分支的功能 )
# 若修改后未提交到暂存区则将其返回至版本库的最新状态,否则回退至暂存区保存的状态 ( 可恢复删除 )
git checkout -- Filename

# 用HEAD所指向的分支下的全部或部分文件来替换暂存区和工作区 
git checkout HEAD [.|filename]

# 回退3个版本
git checkout HEAD~3

# 创建dev分支并切换到dev分支,-b 表示创建并切换
# 注: 相当于两条命令:git branch Name && git checkout Name
git checkout -b dev

# 根据特定历史版本、提交ID、标签号创建分支并进入该新分支 (切换分支的同时工作区的文件会改变)
git checkout -b B_NAME <Branch|2234CX32|Tags>

# 新建和合并分支的操作仅发生在本地版本库中,未与服务端交互,若需同步到远程仓库就要推送这些分支
git push origin --all

# 将远程仓库origin的fix分支迁入到本地fix分支中
git checkout -b fix origin/fix      # 为本地分支设定不同于远程分支的名字,只需将左边换个名字
git checkout --track  origin/fix    # 新版Git支持

# 推送lbranch-2到已有的rbranch-1,用于补充rbranch-1
git checkout lbranch-2
git rebase rbranch-1
git push origin lbranch-2:refs/rbranch-1

# 在切换分支时将当前分支修改的内容一起打包带走并同步到切换的分支下 ...
git checkout --merge <branch>

# 输出已并入当前分支的其他分支 ( 若不需要已经合并的分支可用 "git branch -d NAME" )    
git branch --merged

# 输出未与当前分支合并的分支 ( 删除未进行合并的分支需使用强制删除参数 "git branch -D NAME" )
git branch --no-merged

# ----------------------------------------------------------- git branch & git push

git branch dev          # 创建dev分支 (在当前 commit 对象的基础上创建新的分支指针)
git checkout dev        # 切换到这个新建的dev分支 

# 查看本地及远程仓库的分支信息 (当前分支的名称左侧会标 *)
# 参数 -v 输出各分支最新的提交信息,若仅查看远程仓库相关的分支信息可使用 -r 参数
git branch -av [-r]

# 参数 -vv 会将所有的本地分支输出并包含更多的信息
# 如每个分支正在跟踪哪个远程分支、与本地分支是否领先、落后或都有 ...
$ git branch -vv
#   iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
#   master    1ae2a45 [origin/master] deploying index fix
# * serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
#   testing   5ea463a trying something new
# --------------------------- 输出字段说明:
# "ahead" 是 2,意味着本地有两个提交还没有推送到远程
# master 分支正在跟踪 origin/master 分支并且是最新的
# serverfix 分支正在跟踪 teamone 服务器上的 server-fix-good 分支并且领先 3 落后 1
# 意味着服务器上有一次提交还没有合并进来,同时本地还有三次提交还没有推送到服务器
# 并且 testing 分支并没有跟踪任何远程分支
# ---------------------------
# 需注意这些数字的值来自于从每个服务器上最后一次抓取的数据,它并没有连接服务器
# 它只会告诉用户关于本地缓存的服务器数据
# 如果想要统计最新的领先与落后数字,需在运行此命令前抓取所有的远程仓库:
git fetch --all && git branch -vv

# 查看远程仓库特定分支的详细信息
git remote show BRANCH_NAME

# 重命名本地分支
git branch -m <OLD_BRANCH_NAME> <NEW_BRANCH_NAME>

# 将当前所在分支推送到远程仓库与其对应的分支 ( 远程仓库名 orgin 默认也可以省略 )
git push origin

# 在本地创建A分支后推送到远程仓库"origin"的B分支
git checkout -b A && git push origin A:B

# 使用 --all 参数将本地所有分支推送到远程仓库中与其对应的分支
# 若远程版本比本地新则推送时报错,要先执行 pull 来合并差异后再推送,或使用 –force 强制推送
# 默认推送时不推送标签,除非用 –-tags 指明
git push origin --all [ --tags ]

# push用于将本地commit后的代码更新到远程版本库
# 将本地master分支推送到远程仓库,-f参数为强制,-u参数即设定upstream的同时进行上下游分支的关联
git push -u origin master [-f]

# 设置本地分支与远程分支之间的关联关系
git branch --set-upstream-to <branch-name> origin/<branch-name>

# 在本地创建分支时指定和远程分支的对应关系
git checkout -b other origin/other

# 设置本地分支与远程分支的对应关系
git branch --set-upstram other origin/other

# 删除已经进行合并操作之后的分支时使用-d参数,强制删除未合并的分支时使用-D参数
git branch [-d|-D] BNAME

# 删除远程仓库特定的分支
# 原理是是推送空分支到远程即删除,但严格讲不应这样执行 ( git push [远程名] [本地分支]:[远程分支] )
# 相当于: git push origin --delete BNAME
git push origin :BNAME 

# 在本地创建和远程分支对应的分支
git checkout -b branchname origin/branchname

# 从远程仓库origin中提取dev分支
git checkout -b dev origin/dev

# 当远程仓库删除分支时本地也跟着删除对应的分支(默认本地不删除远程已经不再存在的分支)
git pull --prune

# -----------------------------------------------------------

# 要特别注意的是当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝)
# 可以运行 git merge origin/serverfix 将这些工作合并到当前所在的分支
# 如果想要在自己的 serverfix 分支上工作,可将其建立在远程跟踪分支之上
git checkout -b serverfix origin/serverfix

# ----------------------------------------------------------- git reset

# reset (重置) 用于将当前工作目录完全回滚到指定的版本号

# 清空添加到暂存区的内容(撤销暂存区的记录从而转为已修改但未暂存的状态)
# 既能回退版本,也能把暂存区的修改回退到工作区 (HEAD表示最新版本)
git reset .git reset HEAD [Filename]git unstage [Filename]

# 用版本库中的文件替换暂存区的文件
git reset HEAD -- Filename

# 廖雪峰视频说明: https://www.bilibili.com/video/av51227163
git reset --hard 578IF734F      # 撤回到某个提交点 (版本库,暂存区,工作区全部一致)
git reset --hard HEAD           # 回退到最新的提交版本
git reset --hard HEAD^          # 撤回到上个提交点
git reset --hard HEAD~100       # 回退到之前的第100个版本
# 穿梭前用 git log 可以查看提交历史以便确定要回退到哪个版本
# 返回来用 git reflog 查看命令历史以便确定要回到未来的哪个版本 (因为 git log 也被更改了)
# 注: 
# --hard    表示HEAD、暂存区、工作区都随之改变
# --soft    只变HEAD (工作区和暂存区中的内容不作任何改变,仅把HEAD指向 commit )
# --mixed   改变HEAD、暂存区

# 撤出暂存区中指定的文件,相当于git add的反操作...
git reset filename  # 或 git reset HEAD filename

# 将本地的状态回退到与远程相同
git reset –hard origin/master

# 撤销刚才的提交
# 效果是自  之后的所有改变都会显示在 git status 的"Changes to be committed"中
git reset --soft HEAD^

# -----------------------------------------------------------

# git remote add  
# 添加远程仓库并将其设置为别名"origin" (这是默认命名)
git remote add origin [email protected]/Bluevitality/Bluevitality.git

# 修改远程仓库名称
git remote rename <OLDname> <NEWname>

# 删除远程仓库
git remote rm origin

# 查看远程仓库"origin"的信息
git remote show origin

# 将本地的master分支提交到origin远程仓库 (-f 可强制覆盖远端仓库的版本内容)
# 命令中的master指的是本地仓库的分支名 ...
git push origin [master|Branch_Name] [-f] 
# 或
git push origin master:master [-f]

# 上述命令会自动将master分支名字展开为 refs/heads/master:refs/heads/master
# 这意味着推送本地master分支来更新远程仓库的master分支 ...

# 建立本地分支和远程分支的关联 
git branch --set-upstream <本地分支名>  origin/<远程分支名>

# 从远程仓库拉取本地仓库还没有的数据 (仅拉取远端数据到本地而不合并,需手工合并)
git fetch origin
    
# 将从远程仓库(fetch下来的数据)与当前所在分支进行合并
git merge origin/master

# 切到master分支后把hotfix分支合并进来(合并后可将hotfix分支删除: git branch -d hotfix)
git checkout master && git merge hotfix

# fast forward
# 当合并两个分支时,若顺着一个分支走下去能够到达另一个分支
# 那么Git在合并两者时只会简单的将指针向前推进,因为这种情况下的合并操作没有需要解决的分歧

# 不以fast forward方式合并特定分支到当前分支
# 建议增加--no-ff参数使得执行快速合并时历史记录中仍保留此分支的信息 (相当于普通模式合并)
# 这样合并后的历史有分支,能看出曾做过合并,而fast forward合并看不出来 ...
git merge Name --no-ff [ -m "description" ]

# ---------------------------------------------------- merge Example

# 有时合并操作不会顺利,当在两个不同分支中对同一文件的同一部分进行了不同修改就无法直接合并
# 此时Git虽然做了合并,但没有自动创建新的合并提交,而是会暂停下来等待用户解决这些合并冲突
# 此时可以使用 git status 查看那些因包含合并冲突而处于未合并 "unmerged" 状态的文件 ...
# 出现冲突的文件会包含特殊区段,如:
#   <<<<<<< HEAD:index.html                     # 这表示 HEAD 所指示的版本
#   
#   =======                                     # iss53 分支下的版本在 ======= 的下半部分
#   
# >>>>>>> iss53:index.html
# 为了解决冲突,必须选择使用由 ======= 分割的两部分中的一个,或自行合并这些内容 ...
# 如果对结果满意并且之前有冲突的的文件都已修复和暂存,此时应执行 git commit 来完成合并提交
# ----------------------------------------------------
# 克隆某个特定的分支
git clone -b Bname https://github.com/...
# 克隆所有分支 
git clone https://github.com/... && git branch -r
# 输出如下:
# * master
# origin/HEAD -> origin/master
# origin/master 
# origin/b1
# 查看远程仓库的分支信息
git remote show <origin>
git ls-remote <origin>
git fetch <remote> # 抓取远程分支,但不与本地分支整合
git pull <remote> <branch> # 抓取远程分支的新提交并合并到本地,如果有冲突要先处理冲突
git branch --set-upstream-to origin/branchname <local-branch> # 建立本地分支和远程分支的关联
git branch --track <local-branch> <remote-branch> # 作用同上
git branch <local-branch> origin/master # 作用同上

Git Flow

git 从入门到崩溃_第3张图片


# 分支会在每次提交时自动向前移动
# Master 分支与其它分支没有区别,之所以每个仓库都有 master 分支是因为 git init 默认创建它

# 目录 .git 中有几个比较重要的文件和目录要说明:
# HEAD文件存放根节点信息,其实目录结构就表示一个树型结构,Git采用这种树形结构来存储版本信息,那么HEAD就表示根
# refs目录存储当前版本控制目录下的各种不同引用 (引用指的是本地和远程所用到的各个树分支的信息)
# refs目录有heads、remotes、stash、tags四个子目录,分别存储对不同的根、远程版本库、Git栈和标签的四种引用
# 可通过命令 git show-ref 更清晰地查看引用信息
# logs目录根据不同的引用存储了日志信息,因此只需要代码根目录下的.git就可以记录完整的版本控制信息
# 而不是像SVN那样根目录和子目录下都有.svn目录

你可能感兴趣的:(devops,git)