github学习笔记
基础的 linux 命令
$ clear #清除屏幕
$ echo 'test content' #往控制台输出信息
$ ll #将当前目录下的 子文件&子目录平铺在控制台
$ find 目录名 #将对应目录下的子孙文件&子孙目录平铺在控制台
$ find 目录名 -type f #将对应目录下的文件平铺在控制台
$ rm 文件名 #删除文件
$ mv 原文件 重命名文件 #重命名
$ cat 文件的URL #查看对应文件的内容
$ vim 文件的URL # 按 i 进插入模式 进行文件的编辑
# 按 esc 键&按:键 进行命令的执行
# q! 强制退出(不保存)
# wq 保存退出
# set nu 设置行号
Git配置
一般在新的系统上,我们都需要先配置下自己的 Git 工作环境。配置工作只需一次,以后升级时还会沿用现在的配置。当然,如果需要,你随时可以用相同的命令修改已有的配置。
Git 提供了一个叫做 git config
的命令来配置或读取相应的工作环境变量而正是由这些环境变量,决定了Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
-
/etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用
git config
时用--system
选项,读写的就是这个文件。 -
**~/.gitconfig **文件:用户目录下的配置文件只适用于该用户。若使用
git config
时用--global
选项,读写的就是这个文件。 -
**.git/config **文件:当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件)这里的配置仅仅针对当前项目有效。
每一个级别的配置都会覆盖上层的相同配置
配置用户信息
第一个要配置的是你个人的用户名称和电子邮件地址。这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录:
$ git config --list #显示当前的 Git 配置信息
$ git config -e [--global] #编辑 Git 配置文件(global表示编辑全局的配置文件)
$ git config --global user.name "Jun-wulei" #设置提交代码时的用户名
$ git config --global user.email "Jun-wulei@example.com" #设置提交代码时的用户邮箱
$ git config --global --unset user.email #删除配置信息
使用 Git 来管理项目的基本流程
git init
创建工作目录,对工作目录进行修改git add ./
将修改的内容放到暂存区git commit -m '' 注释内容''
将暂存区的内容生成树对象和提交对象放到版本库
1. git init
初始化仓库
对现在的某个项目开始用 GIT 管理,只需要到此项目所在的目录,执行:git init
来初始化仓库
作用:初始化后,在当前目录下会出现一个名为 .git 的目录,所有 GIT 需要的数据和资源都存放在这个目录下,不过目前,仅仅是按照既有的结构框架初始化好了里边所有的文件和目录,但我们还没有开始跟踪管理项目中的任何一个文件。以下是 .git 目录下包含的文件及其作用。
hooks 目录包含客户端或服务端的钩子脚本
info 包含一个全局性排除文件
logs 保存日志文件
objects 目录存储的所有的数据文件
refs 目录存储指向数据的提交对象的指针(分支)
config 文件包含项目特有的配置文件
description 用来显示对仓库的描述信息
HEAD 文件指示目前被检出的分支
index 文件保存暂存区信息
2. git add
将文件放入暂存区
git add ./
先将工作区的修改生成git对象放到版本库,
再从版本库中的git对象拿出来放到缓存区里面
生成git对象是增量的
只有你在提交的时候,它才会把暂存区的内容生成一个树对象放到版本库,如果有提交的
注释信息,它会把你的树对象拿出来包裹上注释信息,生成一个提交对象,放到版本库
工作目录下的文件有两种状态 已跟踪和未跟踪
已跟踪 有三种状态 已修改 已提交 已暂存
增加删除文件
$ git add [file1] [file2] ... # 添加指定文件到暂存区
$ git add [dir] # 添加指定目录到暂存区,包括子目录
$ git add . # 添加当前目录的所有文件到暂存区
$ git rm [file1] [file2] ... # 删除工作区文件,并且将这次删除放入暂存区
$ git rm --cached [file] # 停止追踪指定文件,但该文件会保留在工作区
$ git mv [file-original] [file-renamed] # 改名文件,并且将这个改名放入暂存区
3. git commit
提交版本库
$ git commit -m [message] # 提交暂存区到仓库区
$ git commit [file1] [file2] ... -m [message] # 提交暂存区的指定文件到仓库区
$ git commit -a # 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -v # 提交时显示所有diff信息
$ git commit --amend -m [message] # 使用一次新的commit,替代上一次提交,如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend [file1] [file2] ... # 重做上一次commit,并包括指定文件的新变化
4. Git 分支
分支的本质
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。
注意
“master” 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。
分支的原理
.git/refs 目录 这个目录中保存了分支及其对应的提交对象
HEAD 引用
当运行类似于 git branch (branchname)
这样的命令时,Git会取得当前所在分支最新提交对应的 SHA-1 值,并将其加入你想要创建的
任何新分支中。
当你执行 git branch (branchname)
时,Git 如何知道最新提交的 SHA-1 值呢? 答案是 HEAD 文件。
HEAD 文件是一个符号引用(symbolic reference),指向目前所在的分支。 所谓符号引用,意味着它并不像普通引用那样包含一个 SHA-1 值。它是一个指向其他引用的指针。
常见的分支类型:
分类 | 分类描述 | 备注 |
---|---|---|
master | 最终发布版本 | 整个项目中有且只有一个 |
develop | 开发分支 | 原则上项目中有且只有一个 |
feature | 功能分支 | 用于开发一个新的功能 |
release | 预发布版本 | 介于develop和master之间的一个版本,主要用于测试 |
hotfix | 修复补丁 | 用于修复master上的bug,直接作用于master |
查看分支
$ git branch #查看分支列表
创建分支和切换分支
$ git branch 分支名 #在当前提交对象上创建新的分支
$ git branch 分支名 commithash #在指定的提交对象上创建新的分支
$ git checkout 分支名 #切换分支
$ git checkout -b #创建分支,并切换分支
**注意:**切换分支改变三个地方 1.HEAD 2. 暂存区 3.工作目录
最佳实践:每次切换分支前 当前分支一定得是干净得(已提交状态)
坑: 在切换分支时,如果当前分支上有未暂存得修改(第一次)或者 有未提交的暂存(第一次)
分支可以切换成功 ,但是这种操作可能会污染其他分支
合并分支
$ git merge dev #dev分支的工作成果合并到当前分支上
快进合并 ---> 不会产生冲突
典型合并--->有机会产生冲突
解决冲突--->打开冲突文件 进行修改 再add commit
$ git merge 分支名
$ git branch --merged #查看哪些分支已经合并到了当前的分支(一旦出现在这个列表就应该删除)
$ git branch --no-merged #查看所有未合并的分支(一旦出现在这个列表 就应该观察一下是不是需要合并)
删除分支
$ git branch -d #删除分支
$ git branch -D #强制删除分支
git 分支的注意点
在切换分支的时候,一定要保证当前分支是干净的!!!
允许切换分支:
分支上所有的内容处于 已提交状态
(避免)分支上的内容是初始化创建 处于未跟踪状态
(避免)分支上的内容是初始化创建 第一次处于已暂存状态
不允许切换分支:
分支上所有的内容处于 已修改状态 或 第二次以后的暂存状态
注意
分支切换会改变你工作目录中的文件,在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。
如 果 Git 不能干净利落地完成这个任务,它将禁止切换分支。
查看项目分支历史 git log --oneline --decorate --graph --all
查看项目分支历史
查看当前分支所指对象 git log --oneline –decorate
(提供这一功能的参数是 --decorate)
隐藏工作区
当前分支进行的开发还没提交需要紧急修复生产bug时可以使用stash功能,把当前工作现场“储藏”起来,等bug修复完成恢复现场后继续工作。或者在分支上的工作做到一半时 如果有切换分支的需求 我们应该将现有的工作存储起来。
隐藏工作区
$ git stash # 隐藏工作区,会在当前分支的工作推到一个栈中
#(其实git stash 有帮我们提交 只是在git log 中不记录,但是在git reflog中会记录)
# 分支切换 进行其他工作 完成其他工作后 切回原分支)
$ git status #此时查看工作区,就是干净的(除非有没有被Git管理的文件)
查看隐藏工作区
$ git stash list #查看存储
恢复并删除隐藏工作区
#第一种方式:
$ git stash apply #将栈顶的工作内容还原 但不让任何内容出栈
$ git stash drop #取出栈顶的工作内容后 就应该将其删除(出栈)-
#第二种方式:
$ git stash pop #恢复的同时把stash内容也删了,相当于git stash apply + git stash drop
分支合并策略
Fast forward 模式
$ git merge dev #正常合并时会使用该模式,直接将master指针指向分支。
$ git log --graph --pretty=oneline --abbrev-commit #查看日志记录看不出来曾经做过分支合并
禁用 Fast forward 模式
$ git merge --no-ff -m "描述信息" dev #--no-ff参数,表示禁用Fast forward
$ git log --graph --pretty=oneline --abbrev-commit #可以用普通模式合并,合并后分支历史上可以看出分支信息,能看出来曾经做过合并
分支合并冲突解决步骤
-
尝试合并分支
$ git merge dev #将dev分支尝试合并到当前分支
-
存在冲突时查看冲突文件
$ git status
-
打开冲突文件查看冲突位置并手动解决
<<<<<<< HEAD 分支1冲突内容 ======= 分支2冲突内容 >>>>>>> feature1
-
手动解决冲突后再提交
$ git add readme.txt $ git commit -m "解决冲突"
-
查看分支合并情况
$ git log --graph --pretty=oneline --abbrev-commit
bug分支
每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
在bug分支将bug修复后合并到master分支,将bug分支删除,此时其他分支上该bug依然存在;比如要在dev分支上修复,我们只需要把修复bug的提交所做的修改“复制”到dev分支(只复制bug改动),Git专门提供了一个cherry-pick命令,让我们能复制一个特定的提交到当前分支,命令如下:
$ git branch #查看当前分支
$ git switch branch dev #切换到dev分支
$ git cherry-pick 4c805e2 #合并bug提交的改动并提交,4c805e2为提交记录id
Feature 特色分支
每添加一个新功能,最好新建一个feature分支,在上面开发,完成后合并,最后删除该feature分支。
①创建一个分支用来开发新功能
$ git checkout -b feature_01 #创建并切换分支feature_01
②开发功能完成后提交到本地仓库 add/commit,合并到其他分支,然后删除改功能分支
③废弃该分支
$ git branch -d feature-vulcan #git会提示是否确定要删除,确定用-D参数再执行一次命令
$ git branch -D feature-vulcan #强制删除
5.查看信息
$ git ls-files -s #查看当前暂存区的样子
$ git status #检查当前文件状态
$ git log #默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面。这个命令会列出每个提交的 SHA-1 校 验和、作者的名字和电子邮件地址、提交时间以及提交说明
$ git log --pretty=oneline
$ git log --oneline
$ git status # 显示有变更的文件
$ git log --stat # 显示commit历史,以及每次commit发生变更的文件
$ git log -S [keyword] # 搜索提交历史,根据关键词
$ git log [tag] HEAD --pretty=format:%s # 显示某个commit之后的所有变动,每个commit占据一行
$ git log [tag] HEAD --grep feature # 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
$ git log --follow [file] # 显示某个文件的版本历史,包括文件改名
$ git whatchanged [file]
$ git log -p [file] # 显示指定文件相关的每一次diff
$ git log -5 --pretty --oneline # 显示过去5次提交
$ git shortlog -sn # 显示所有提交过的用户,按提交次数排序
$ git blame [file] # 显示指定文件是什么人在什么时间修改过
$ git diff # 显示暂存区和工作区的差异
$ git diff --cached [file] # 显示暂存区和上一个commit的差异
$ git diff HEAD # 显示工作区与当前分支最新commit之间的差异
$ git diff [first-branch]...[second-branch] # 显示两次提交之间的差异
$ git diff --shortstat "@{0 day ago}" # 显示今天你写了多少行代码
$ git show [commit] # 显示某次提交的元数据和内容变化
$ git show --name-only [commit] # 显示某次提交发生变化的文件
$ git show [commit]:[filename] # 显示某次提交时,某个文件的内容
$ git reflog # 显示当前分支的最近几次提交
git的撤销和重置(版本回退)
- 工作区 ----- 如何撤回自己在工作目录中的修改 :
git checkout --filename
- 暂存区 ----- 如何撤回自己的暂存 :
git reset HEAD filename
- 版本库 ----- 如何撤回自己的提交 :
1:注释写错了,重新给用户一次机会修改注释git commit --amend
git reset --hard HEAD^ #回退到上一个版本,HEAD表示当前版本,一个^表示一个版本
git reset --hard HEAD~100 #回退到往上100个版本
git reset --hard commitHash #回退到指定版本,commit_id为提交记录id
指令:
# 恢复暂存区的指定文件到工作区
$ git checkout [file]
# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout [commit] [file]
# 恢复暂存区的所有文件到工作区
$ git checkout .
# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset [file]
# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard
# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset [commit]
# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard [commit]
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]
# 新建一个commit,用来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应用到当前分支
$ git revert [commit]
reset 三部曲
1:移动 HEAD
git reset --soft HEAD~
只动HEAD(带着分支一起移动)
2:更新暂存区(索引)
git reset --mixed HEAD~
动了HEAD (带着分支一起移动) 动了暂存区
3:更新工作目录
git reset --hard HEAD~
动了HEAD (带着分支一起移动) 动了暂存区 动了工作区
git checkout commithash & git reset --hard commithash 区别
1:checkout 动HEAD 不带着分支一起走 动暂存区和工作区 --hard 动HEAD 而且带着分支一起走 还动暂存区和工作区
2:checkout 对工作区是安全的 --hard 是强制覆盖工作目录
git checkout --filename
git checkout commithash(分支名)
相比于git reset --hard commithash --filename
第一步 第二步都没做
只会动了工作目录
git checkout commithash <file>
将会跳过第一步
更新暂存区
更新工作目录
注意:
git checkout – [file] 是一个危险的命令,这很重要。 你对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它。
除非你确实清楚不想要那个文件了,否则不要使用这个命令
HEAD
HEAD 是当前分支引用的指针,它总是指向该分支上的最后一次提交。
这表示 HEAD 将是下一次提交的父结点。通常,理解 HEAD 的最简方式,
就是将它看做 当前提交 的快照。
git cat-file -p HEAD
查看当前提交对象
git ls-tree -r HEAD
查看当前提交对象对应的树对像的内容
使用 git 关联远程库
关联远程仓库
$ git remote add origin http://github.com/Jun-wulei/Memorandum.git # 添加远程库,并给该远程库创建 origin 的别名
克隆远程仓库并创建本地dev分支与远程仓库origin的dev分支关联
$ git clone 远程仓库url #默认克隆远程仓库master分支
$ git checkout -b dev origin/dev #克隆后在本地创建dev分支并关联远程仓库origin的dev分支,本地和远程分支的名称最好一致
删除关联
$ git remote rm origin #删除当前本地仓库与远程仓库origin的关联
查询关联
$ git remote #远程库的信息,只显示远程仓库名字
$ git remote -v #显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。
将远程仓库更新到本地
git pull #远程库内容更新到本地,相当于下边两个命令组合
git fetch #从远程分支拉取代码,可以得到远程分支上最新的代码
git merge #合并
把本地仓库内容推送到远程仓库
git push origin master #将本地仓库内容推送到远程仓库
配别名
Git 并不会在你输入部分命令时自动推断出你想要的命令。 如果不想每次都输入完整的 Git 命令,可以通过 git config 文件来轻松地为每一个命令设置一个别名。
git config --global alias.st status #告诉Git使用st就表示status,git status 与 git st执行效果一样*
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
当要输入 git commit 时,只需要输入 git ci
打tag(标签)
Git 可以给历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点(v1.0 等等)
查看标签
$ git tag # 列出所有tag
$ git show tagname #查看特定标签,git show 可以显示任意类型的对象(git 对象 树对象 提交对象 tag 对象)
添加标签
Git 使用两种主要类型的标签:轻量标签 与 附注标签
轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用
$ git tag v1.4 # 新建一个tag在当前commit
$ git tag v1.4 commitHash # 新建一个tag在指定commit
附注标签是存储在 Git 数据库中的一个完整对象。 它们是可以被校验
的;其中包含打标签者的名字、电子 邮件地址、日期时间;还有一个标签信息;通常建议 创建附注标签,这样你可以拥有以上所有信息;但是如果你只是想用一个临时的标签,或者因为某些原因不想要保存那些信息,轻量标签也可用的
$ git tag -a v1.4
$ git tag -a v1.4 commitHash
$ git tag -a v1.4 commitHash -m "my version 1.4"
远程标签
#默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上
$ git push origin [tagname]
#如果想要一次性推送很多标签,也可以使用带有--tags选项的 git push 命令。这将会把所有不在远程仓库服务器上的标签全部传送到那里
$ git push origin --tags
删除标签
$ git tag -d [tagName] # 删除本地tag(该命令并不会从任何远程仓库中移除这个标签,你必须使用下面这个命令来删除远程tag)
$ git push origin :refs/tags/[tagName] # 删除远程tag
检出标签
如果你想查看某个标签所指向的文件版本,可以使用 git checkout 命令
$ git checkout tagName
虽然说这会使你的仓库处于“分离 头指针(detacthed HEAD)”状态。在“分
离头指针”状态下,如果你做了某些更改然后提交它们,标签不会发生变化,但你
的新提交将不属于任何 分支,并且将无法访问,除非访问确切的提交哈希。因此,
如果你需要进行更改——比如说你正在修复旧版本的错 误——这通常需要创建一
个新分支:
$ git checkout -b version2
忽略文件(.gitignore)
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。
*.[oa] 忽略所有以 .o 或 .a 结尾的文件(一般这类对象文件和存档文件都是编译过程中出现的,我们用不着跟踪它们的版本)
*~ 忽略所有以波浪符(~)结尾的文件(许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本)
你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件
GitHub有一个十分详细的针对数十种项目及语言的.gitignore文件列表,地址:https://github.com/github/gitignore