Git基础操作

首先,我们需要安装好Git,可以在Git官网上下载

http://git-scm.com/download

Git是一个高可配置软件。首先,我们可以用config命令配置一下用户名和邮箱:

git config --global user.email "hans@163.cnn"

第一个Git项目

创建版本库,用于存储该项目本身及其历史,打开项目目录,使用init命令
init命令会在上述目录创建一个名为.git的隐藏目录,并在其中创建一个版本库。

cd demo
git init

输出:
Initialized empty Git repository in C:/phpStudy/PHPTutorial/WWW/demo/.git

首次提交
接下来将foo.txt和bar.txt这两个文件添加到版本库中去
分两步走,第一步先用add命令将文件添加到暂存区,第二步再用commit命令将修改传送到版本库中。

git add foo.txt bar.txt
git commit --message "添加新文件bar.txt foo.txt"

查看状态

git status

查看修改细节
可以通过diff命令来显示每行被修改的内容,但是diff的输出非常难读。最好使用图形化工具
查看foo.txt文件工作区(本地)版本与历史版本的区别,HEAD为对比上次commit,更久远的对比可以输入hash版本号

git diff foo.txt
git diff b4b8826e foo.txt

提交修改
对修改过的文件使用 add命令,
对删除的文件使用rm命令
然后用commit命令提交这些修改

git rm bar.txt
git add foo.txt bar.html
git commit --message "修改foo.txt ,删除bar.txt,添加新文件bar.html"

显示历史
log命令可用来显示项目的历史,并按降序排列出来
–oneline 历史版本以简单短形式展示(注意参数前是两个-)
–pretty=oneline 历史版本以完整hash形式展示

git log

Git 的协作能力

克隆版本库
新开发者需要有一个属于他的版本库副本,该副本包含所有原始库的信息与项目的历史信息。
使用clone来创建一个克隆体

git clone /demo /demo-clone/

从另一版本库中获取修改
我们来修改demo/foo.txt文件,并add && commit添加到版本库
回到克隆版本库demo-clone中,执行pull 命令,pull命令从原始版本库中取回新的修改,将与克隆体中的本地修改进行对比,并合并了两边的修改,创建一次新的提交,这个过程就是所谓合并(merge)

git pull

创建共享版本库
除了pull可以从其他版本库中取回相关提交外,也可以用push命令将提交传送给其他版本库。
push命令只适用于没有开发者在上面开展具体工作的版本库,最好创建一个不带工作区的版本库,我们称之为裸版本库(bare repository)。裸版本库通常可被用来充当开发者们传递提交的汇聚点。

git clone --bare /demo
git commit --message "创建共享版本库"

上载修改

cd demo
git push ../demo.git master

取回修改

cd demo-clone
git pull /demo.git master

提交究竟是什么

–stat参数观看提交中究竟包含了哪些重要信息

git log --stat -1

访问权限与时间戳
git会保存每个文件原有的访问权限,即POSIX文件权限,包含读、写、执行3种。但不保存时间戳,在执行检出(checkout)操作时,文件时间会设为当前时间

散列值
乍看之下,40位字符的散列值的确太长,毕竟其他版本控制器只使用最简单的序列数,例如subversion。但是git选择散列值也是有原因的
1 这样的散列值可以本地生成,无需与其他计算机或中央服务器通信生成,可达到随时随地创建新的提交,而2次提交得到相同的散列值概率非常低,因为面对的值有2^160种。
2 最重要的是提交的散列值,也是该软件版本的汇总信息,我们都能通过git的fack命令查看版本库的完整性。如果内容与相应的散列值不匹配,我们就会得到错误报告。

提交历史
版本库中所包含的不仅仅是一个个独立的提交,同时还存储了这些提交之间 关系。

查看修改
查看foo.txt本地与上次提交不同

git diff HEAD foo.txt

查看历史
git log 有多个参数,
-n 部分输入 git log -3 输出最后3次提交
–oneline 格式化输出,只显示概述信息
–format=fuller 格式化输出,显示更多细节信息

git log -3
git log --oneline
git log --format=fuller

–stat 显示每次提交修改了哪些文件
–shortstat 显示多少文件被修改、新增、或删除
–graph 显示各提交之间的关系

git log --stat
git log --shortstat
git log --graph

多次提交

status命令
changes to be committed 被纳入下次提交的文件
changed but not updated 列出已被修改,但尚未注册到下次提交的文件
untracked files 列出所有新增未被跟踪的文件
–short使输出更紧凑

git status --short

将foo.txt文件移出暂存区

git reset HEAD foo.txt

.gitignore 忽略非版本控制文件
对于那些自动生成、由编辑器创造的备份、临时文件,可不置于版本库控制之下
如果一个项目由多种语言编写,也可在子目录下放置.gitgnore文件,用于控制子目录文件
但是请注意,如果某个文件已经存在于远程仓库了,也就是说某个文件已经被版本控制了,如果将该文件添加到.gitignore中,是无法生效的。因为.gitignore是只能作用于尚未被纳入版本控制的(Untracked Files)文件,如果文件已经存在于远程库中,自然也就无法生效了。
于是就此衍生了一个问题:.gitignore怎么忽略已经被版本控制的文件?
1使用命令git rm --cached filename,然后将该文件写入.gitignore中即可。
2可以通过update-index命令的 --assume-unchanged选项来做到这一点

git rm --cached filename
git update-index --assume-unchanged logs/*.log

或者

git update-index --skip-worktree config/app.php
git update-index --no-skip-worktree config/app.php

git rm --cached filename 删除的是追踪状态,而不是物理文件。由于该文件原本已经被版本控制了,使用了该命令后,虽然保留了工作区的该文件,但是却会在暂存区中生成一个删除了该文件的记录,如果此时进行commit,就会把版本库里的该文件给删掉了,如果push到远程库,也会被删掉。所以一些要忽略但是重要的配置文件不能使用这种方式删除。

储藏
当一个功能写到一半时,一个紧急问题需要处理,而工作区的内容还不能提交,这个情况,我们可以使用stash命令先将这些修改保存在本地,日后再来处理
–pop 将储藏内容恢复到工作区
list 储藏列表

git stash 
git stash list
git stash pop

分支

查看分支,切换分支,创建并切换到新分支
checkout被拒绝怎么办?–force放弃本地修改

git branch
git checkout a-branch
git checkout -b b-branch
git checkout --force a-branch

重置分支指针,-d删除分支,-D强制删除分支
reflog 查看所有命令执行记录, 知道分支散列值可以恢复删除的分支

git reset --hard 392ea5b
git branch -d b-branch
git branch -D b-branch
git reflog 
git branch a-branch 742dcf6

合并分支
当这个分支要进行合并时,git要做的工作就非常简单了,只要前移一个指针即可,不再产生合并提交,这种情况称为快进合并。
快进优点是简化版本库历史,并使其线性发展,缺点则是不能根据已合并和历史记录来看版本库的这一发展。 --no-ff不快进合并

git merge a-branch
git merge --no-ff a-branch

创建裸版本库
裸版本库无工作区,用于充当push提交汇聚点
pull 拉共享版本库代码,push提交到共享版本库

git clone --bare demo demo.git
git push demo.git master
git pull demo.git master

版本库间的交换

给另外版本库起个名字 remote add alias_name , 删除名称 remote rm alias_name
查看源版本库和可用于推送和接收的路径
获取数据,将克隆版本库和数据获取到本地版本库 fetch , pull = fetch + merge

git remote add myclone file://tmp/git-book-clone.git
git remote rm myclone
git remote --verbose
git fetch myclone

版本标签

创建一个普通的标签 v.0.1
推送一个标签到远程仓库 --tags 或者 git push origin v.0.1
当前究竟存在哪些标签,支持通配符 *
删除一个标签 v.0.1

git tag v.0.1 
git push --tags
git tag -l v.0*
git tag -d v.0.1

技巧

别名 alias, --global 设为全局别名,不加即只对当前库项目有效

git config --global alias.ci commit



Git 教程

创建版本库

创建一个空目录,通过init把这个目录变成git仓库
如果没有出现.git目录,使用 ls -ah命令显示隐藏目录

mkdir learngit
git init
ls -ah

把一个文件加入Git仓库需要两步
1用 add命令把文件加入暂存区
2用 commit命令把暂存区的内容提交到版本库, --message是对本次提交的说明
status命令让我们时刻掌握工作区和暂存区的动态
diff命令可查看一个文件具体改了哪些内容

git add readme.txt
git status
git diff readme.txt
git commit --message "wrote a readme file"

版本回退
使用 log命令查看版本库提交历史
reset操作版本回退,参数HEAD 表示当前版本,HEAD^ 表示上一个版本,HEAD^^ 上上个版本,100个^ 表示往上100个版本,直观写法是HEAD^100,标准写法是使用hash版本号
reset HEAD回退到上一个版本
reset +版本号回退到指定版本

git reset --hard HEAD^ 
git reset --hard 6a51

回退后第二天后悔了,想恢复到新版本怎么办?
使用 reflog命令查看版本库操作历史,与log有什么不同呢?reflog会记录你每次操作的版本库和操作版本库的命令,而log主要记录版本提交历史
使用reset命令在版本之间穿梭,git 版本回退速度非常快,在git内部有一个指向 HEAD版本的指针,当你回退时,git只是把指针指到了回退版本。

git reflog
git reset --hard c2d22

工作区和暂存区

丢弃工作区内容
git checkout – file
一种是 file 还没有放入暂存区,撤销就回到和版本库一样的状态
一种是 file 已经添加到暂存区,又作了修改,撤销就回到添加到暂存区后状态
总之,就是让这个文件回到最近一次git commit或git add时的状态。
git checkout – file命令中的–很重要,没有–,就变成了“切换到另一个分支

git reset HEAD file
reset 同样可以把暂存区的修改撤销掉
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区

场景1:当你修改了工作区某个文件的内容,想丢弃时,用命令git checkout – file。
场景2:当你不但修改工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作。
丢弃工作区的文件

git checkout -- <file>

丢弃暂存区的文件

git reset HEAD <file>

删除文件

git rm log.txt
git commit -m '删除log.txt文件'

恢复删除的文件到最新版本,原理是用版本库里的版本替换了工作区的版本。

git checkout -- log.txt

从远程库克隆

首先,登录github,在右上角点击 “New repository"按钮,创建一个新的仓库
在 “Repository name *” 中填入项目名称
勾选 “Initialize this repository with a README”,以便git为项目自动创建” README.md"文件
下一步,使用git clone命令克隆一个本地库,项目地址在Code->Clone or download复制
github给出的项目地址不止一份,还有https等协议,https速度慢且每次推送都必须输入口令

git clone https://github.com/username/gitskill.git

分支管理

假如你正在完成一个功能,这个功能完成80%,而此时,一个紧急任务突然进来了,你不能提交未完成的代码,也不可能删除,此时,使用分支功能可以让你在另一个平时世界完成紧急任务并上线。
新建dev分支,git新建一个dev指针指向master相同的提交,同时HEA指向dev,就表示当前分支在dev上。
创建dev分支,后台只是增加了一个dev指针,改改HEAD的指向,工作区文件没有任何变化

把dev合并到master,git是怎么做的呢? 就是直接把master指向dev的当前提交,就完成了合并。
而dev分支可以直接删除,却不会影响master分支

创建分支
branch 创建一个新分支,checkout切换到指定分支

git branch dev
git checkout dev

创建并切换分支
checkout -b是创建并切换分支的简略写法,效果与branch + checkout一样。

git checkout -b dev

查看当前分支
标识"*"号的是当前分支

git branch

在dev分支修改文件并操作commit后,切换到master分支发现内容并没有改变,这是因为那个提交是在dev分支上,而master分支此刻的提交点并没有变

合并 dev分支
注意返回值 "Fast-forward"信息,告诉我们,这次合并是快进模式,也就是直接指向dev分支当前提交

git merge dev

删除分支
合并完成后,就可以放心删除dev分支了

git branch -d dev

Git鼓励大量使用分支

查看分支:git branch

创建分支:git branch

切换分支:git checkout

创建+切换分支:git checkout -b

合并某分支到当前分支:git merge

删除分支:git branch -d

冲突
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,修改后重新 add commit提交
用–graph参数可以看到分支合并状态
–oneline以简短概述形式展示

git log --graph --oneline

分支管理策略
合并分支时,如果可能,Git会用Fast forward模式,但这种模式,删除分支后,会丢掉分支信息。
合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
–no-ff参数,表示禁用Fast forward

git merge --no-ff -m "merge with no-ff" dev

Bug分支
分支开发工作只进行到一半还没法提交,但bug需要紧急修复,怎么办?
可以把当前工作现场“储藏”起来 stash 命令

git add .
git stash

首先确定要在哪个分支上修复bug,假定要在master分支上修复,就从master创建临时分支

git checkout master
git checkout -b issue-101
git add foo.txt
git commit -m 'fix bug 101'

修复完成后,切换到master分支,并完成合并,最后删除issue-101分支

git checkout master
git merge -no-ff -m'merged bug fix 101 issue-101

修复完成后,现在是时候回到dev分支干活了

git checkout dev
git status

工作区是干净的,刚才的工作现场去哪了?

git stash list

输出: stash@{0}: WIP on hhh: d9bb0c0 Initial commit

输出可以看出,工作现场还在,但git把stash内容存在某个地方了,恢复方法有两个:
一是用 git stash apply ,但是恢复后,stash内容并不删除,需要用git stash drop来删除
两是用 git stash pop,恢复的同时把stash内容也删除。

git stash pop

你可以多次stash ,恢复的时候,先用 git stash list查看序号,然后恢复指定stash

git stash list
git stash apply stash@{0}

多人协作

查看远程库信息
git remote
显示更详细的信息, remote -v, fetch抓取地址,push推送地址

git remote
git remote -v

推送分支
推送到指定分支

git push origin master
git push origin dev

创建远程origin 的dev分支到本地

git checkout -b dev origin/dev

指定本地dev与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接

git branch --set-upstream-to=origin/dev dev

小结
查看远程库信息,使用git remote -v;
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

Rebase
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

git rebase

标签

什么场景会用到标签? 请把上周一的那个版本打包发布,版本号是v0.1。而不是复制把那一堆不好记的哈希字符串7a5826e。。。
标签总是与hash版本号是挂钩的

基础操作
打一个新标签,默认打在最新提交的commit上
如果上周commit时忘记打标签了,方法是找到历史提交hash版本号,打上就可以了
还可以创建带说明的标签,用-a指定标签名,-m指定说明文字

git tag v0.1
git tag v0.1 f52c612
git tag -a v0.2 -m "说明信息备注原因..."

查看标签列表,删除标签

git tag
git tag -d v0.1

推送标签
创建的标签只存储在本地,推到标签到远程需要单独使用push命令
可以指定推送某一个标签 < tagname >,或者推送全部标签 --tags

git push origin v1.0
gitpush origin --tags

删除远程标签
先删除本地,然后从远程删除也是使用push命令,

git tag -d v0.1
git push origin :refs/tags/v0.1

推送、删除是否成功要登录在github->code->releases查看

配置别名

如果敲git st就表示git status命令, ci就表commit,怎么做
 --global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
加 --global针对当前用户起作用,配置文件在一个用户主目录下的隐藏文件.gitconfig中,[alias]下
不加 --global针对当前仓库起作用,配置文件在项目的 .git/config中,[alias]数组下
配置命令全局别名

git config --global alias.st status`
git config --global alias.ci commit

配置参数别名
输入 git ll 达到 git log --oneline --graph命令的效果
输入 git plrf ,git phrf 达到拉取和推送 origin refactor分支的效果

git config --global alias.ll "log --oneline --graph"
git config alias.plrf "pull origin refactor"
git config alias.phrf "push origin refactor"

摘自
《Git学习指南》、廖雪峰的Git教程

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值