git学习笔记

学习资料:Git教程,廖雪峰;网络

仓库创建与查看和修改本地git用户名和邮箱地址

这个 用户名邮箱地址 只是用来记录本地 Git 提交信息的一个标识,和你远程仓库账号下的 用户名邮箱地址 没有任何关系。

# 从远程端通过git clone方式,则本地自动创建仓库。否则,为本地目录手动创建仓库:
git init  # 创建仓库,在当前目录中生成一个.git 目录(含有.git目录的目录即是git仓库)

# 查看
git config user.name
git config user.email

# 初次设置或者修改,xxx 处填写你的用户名或邮箱地址
git config --global user.name "xxx"
git config --global user.email "xxx"

# 修改指定项目的用户名和邮箱地址,cd 到指定项目的仓库下
git config user.name "xxx"
git config user.email "xxx"

git代码状态转换介绍

img
图片cr. 西山在山南

工作区:仓库所在本地目录的所有内容

缓存区 (stage):git add提交

版本库(也称为仓库 ,包含master或其他分支): git commit提交。Git为我们⾃动创建的第⼀个分⽀master,以及指向master的⼀个指针叫HEAD。

文件状态:

untracked / unstaged:表示是工作区新文件,没有被add过。
在这里插入图片描述
not staged: 表示add过的文件,即跟踪文件,再次修改没有add,即没有添加到暂存区。关联的状态反馈,“Changes not staged for commit”。

stage:已经被Git跟踪的状态,包括staging状态和staged状态。与这两种状态相关联的状态反馈有:针对缓存区未进入版本库,“Changes to be committed”.
在这里插入图片描述

与远程端的差异展示:
在这里插入图片描述

本地使用及操作

添加⽂件到Git仓库,分两步:

# git add 将文件提交到缓存区 (可反复多次使⽤)
git add file1 file2 file3  # 添加多个
git add file1  # 添加多次
git add file2
git add file2
git config/*  # 指定目录或格式的文件
git add 文件夹名
git home/*.php
git add .  # 所有文件
git add --all

# 缓存区提交到版本库
git commit -m "add new file"  # -m后⾯输⼊的是本次提交的说明

基本的git工作流程:

1.在工作目录中修改文件。

2.暂存文件,将文件的快照添加到暂存区(git add)。

3.提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。

查看仓库的当前状态,以及文件状态差异查询 (工作区,缓存区,仓库区)

1.查看当前状态

git status  # 仓库的当前状态,各状态含义见文件状态查询

2.git diff反馈结果信息介绍

若无任何反馈,则代表没有差异。(git理念,没有消息就是最好的消息)

在这里插入图片描述

如上图所示:

第一行,表示结果为git格式的diff,比较的版本是a版本(变动前)与b版本(变动后)。

第二行,表示两个版本的git哈希值,index区域 1416324与工作区域的8c710d1进行比较。(最后的六位数字是对象的模式(普通文件,644权限))

第三、四行,表示比较的两个文件,"—“表示变动前的版本,”+++"表示变动后的版本。

第五行,表示变动的位置用两个@作为起首和结束,前面的"-1,3"分成三个部分:减号表示变动前文件(即a文件),"1"表示第1行,“3"表示连续3行。合在一起,就表示下面是变动前文件从第1行开始的连续3行。同样的,”+1,5"表示变动后,b文件从第1行开始的连续5行。

后面,表示变动的具体内容,显示变动的行以及变动对应的上下文各显示3行。每一行最前面的标志位,空表示无变动,减号表示第一个文件删除的行,加号表示第二个文件新增的行。

3.git diff命令常见用法

# 1.工作区 VS 缓存区
git diff <filename> # 查看文件在工作目录与暂存区同名文件的差异。
git diff <branch> <filename> # 指定分支下缓存区同名文件的差异。(分支管理间后续内容)

# 2.缓存区 VS git仓库
git diff --staged(或cached) <filename>
git diff --staged(或cached) <commit> <filename> # 指定仓库版本

# 3.工作区 VS git仓库
git diff <commit> <filename> # 查看工作目录同Git仓库指定 commit 的内容的差异

# 4.git仓库 VS git仓库
git diff <commit> <commit> 

  1. 以上命令可以不指定,则是对所有文件进行操作。注意,git diff仅针对相同的文件名的文件查看差异,不具备检测出新添加的文件的功能。

  2. 涉及和 Git仓库 对比的,均可指定 commit 的版本,默认HEAD版本。
    HEAD表示当前版本; 上一个版本是 HEAD^,上上一个版本是 HEAD^^,往上100个版本可以写成 HEAD~100;也可以仅指定前几位字符(一般选7位)。

版本回退

版本回退重点在于回退到git仓库中的某个commit版本。查看历史的版本记录。

# 某些编译工具如vscode等也会提供git log的可视化工具。
git log  # 查看git仓库由最近到最远的版本提交历史记录
git log --pretty=oneline # 仅展示必要信息:版本号 提交说明

git reset --hard <commit>  #版本回退(稍后补充介绍两者区别)
git reset <commit>  #版本回退,是git reset --soft的缺省形式 

git reflog   # 查看命令历史,以便确定要回到未来的哪个版本。

在这里插入图片描述

在这里插入图片描述

cat(英文全拼:concatenate)命令用于连接文件并打印到标准输出设备上。

补充:git reset --hardgit reset --soft的区别:

(1)两者用于对git仓库中仓库版本的回退,但对缓存区和工作区的影响不相同。

(2)--hard模式下,会将工作区的内容也修改到与要回退的版本一致的状态; 而--soft不会对工作区起效果,仅对版本仓库和缓存区进行回退。

(3)git reset HEAD可用于撤销尚未commit的修改,使缓存区或工作区回退到与最新版本一致。

撤销修改

在不同状态下,对文件进行了修改,如何撤销,主要分三种情况:

场景1:当你改乱了⼯作区某个⽂件的内容,还未添加到缓存区,想直接丢弃⼯作区的修改时,⽤命令git checkout -- file

git checkout -- file命令中的--很重要,没有--,就变成了“创建⼀个新分⽀”的命令 (注意--与文件名之间有空格).

场景2:当你不但改乱了⼯作区某个⽂件的内容,还添加到了暂存区时,想丢弃修改,可以采用回退到最新版本方法git reset HEAD file,采用--soft/hard模式可以自由选择,如果是--soft则回到场景1。当不指定具体文件或文件夹时,则对全部文件进行操作。

场景3:已经提交了不合适的修改到版本库,但没有推送到远程库,想要撤销本次提交,参考版本回退⼀节。(推送到远程端这个问题,可以不必考虑,本地撤销修改后再次push即可。)

删除文件

在不同状态下,对文件进行了删除,如何应对:

场景1: 文件既没有git add 也没有 git commit,属于untracked状态。此时对文件的删除操作属于本地操作,git不具有追踪和回溯效果,按本地文件常规处理即可。

场景2:如果文件已经添加到缓存区(无论是否提交至版本库),此时删除了本地文件。此时分两种情况:

(1)则如果本意是为了删除文件,则采用git rm filename命令从最近一次提交的缓存区内容中删除该文件。如果该文件已经被commit到版本库,则还需再执行一次 git commit -m “delete filename”,将该删除同步到git仓库端。

(2)如果是误删除,需要恢复该文件,则采用命令git checkout -- file,丢弃工作区的修改(这里是删除操作)。这里恢复的是最近一次提交到缓存区的内容。(如果该缓存区内容已经commit,则与git 仓库保持一致)

团队开发及操作

分支管理

1.创建与切换分支

git checkout -b dev # 创建并切换值dev分支
# 相当于下面两条命令
git branch dev # 创建分支
git checkout dev # 切换到dev分支

git branch # 列出所有分⽀,当前分⽀前⾯会标⼀个*号
git branch -r # 列出所有远程分⽀,r也就是remote,此时不会有*的出现
git branch -a # 查看全部分支,包括远程分支

在这里插入图片描述

2.合并与删除分支

git merge dev # 用于将dev分支合并到当前分支
git branch -d dev # 删除dev分支

# 当分支合并时遇到冲突,则合并失败,由git status找到冲突的文件,直接打开该文件,修改内容解决冲突后,重新提交。Git⽤<<<<<<<,=======,>>>>>>>标记出不同分⽀的内容。
git add readme.txt
git commit -m "conflict fixed"
git log --graph --pretty=oneline --abbrev-commit # 带参数的git log也可以看到分⽀的合并情况

上述合并分支采用的是”fast forward模式“,在该模式下,删除分支后,分支信息对丢掉,可以采用禁用”fast forward模式“,git会在merge时生成commit,从分支历史中可以看出分支信息。

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

因为本次合并要创建⼀个新的commit,所以加上-m参数,把commit描述写进去。

在这里插入图片描述

3.分支策略

在实际开发中,我们应该按照⼏个基本原则进⾏分⽀管理:
⾸先,master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯干活;
那在哪干活呢?干活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布时,再把dev分⽀合并到master上,在master分⽀发布1.0版本;
你和你的⼩伙伴们每个⼈都在dev分⽀上干活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就可以了。

在这里插入图片描述

4.Feature分⽀

添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新功能,最好新建⼀个feature分⽀,在上⾯开发,完成后,合并,最后,删除该feature分⽀。顺利的话,开发完成后Feature分支将合并到dev分支上,然后删除。

但是,如果因其他原因彻底放弃该功能,则要丢弃⼀个没有被合并过的分⽀,可以通过git branch -D name强⾏删除。

5.bug分支

修复bug时,我们会通过创建新的bug分⽀(一般从master分支上新建)进⾏修复,然后合并,最后删除;

当⼿头⼯作没有完成时,先把⼯作现场git stash⼀下,然后去修复bug,修复后,再git stash pop,回到⼯作现场。

git stash # “储藏”⼯作现场
git stash list # 查看

# 恢复工作现场方式1
git stash apply # 恢复,但是恢复后,stash内容并不删除(默认是最近一次stash)
git stash drop # 删除
# 恢复工作现场方式2
git stash pop # 恢复的同时删除stash内容
git stash apply stash@{0} # 恢复指定的stash

一般而言,关于分支推送:
• master分⽀是主分⽀,因此要时刻与远程同步;
• dev分⽀是开发分⽀,团队所有成员都需要在上⾯⼯作,所以也需要与远程同步;
• bug分⽀只⽤于在本地修复bug,就没必要推到远程了,除⾮⽼板要看看你每周到底修复了⼏个bug;
• feature分⽀是否推到远程,取决于你是否和你的⼩伙伴合作在上⾯开发。

远程仓库

1.远程库地址相关操作

git remote # 查看已关联远程库名(多个将全部列出)
git remote -v # 查看已关联远程库名的抓取和推送地址。如果没有推送权限,就看不到push的地址。
git remote show <remote_repo_name> # 查看某个远程仓库的具体信息

在这里插入图片描述

git remote add <remote_repo_name> <git_url>  # 添加, git_url以.git结尾
git remote remove <remote_repo_name>  # 删除
git remote rename <old_name> <new_name>  # 重命名
git remote set-url <remote_repo_name> <git_url> # 重置远程仓库地址

当本地的git远程地址发生了变化,需要将remote_url改成新的地址,如何操作?

方式1:删除本地目录,重新git clone (不建议)

方式2:删除已有远程关联,并添加新的关联

方式3: 通过 git remote set-url origin 重置远程仓库地址

2.上游仓库

img

在远程仓库中,最常见的两个约定俗称的名字是 origin和upstream。

origin,源仓库,一般为git clone的仓库,克隆后默认提交和拉取的地址;upstream,上游仓库,一般为origin fork 的仓库,fork相当于另一种clone方式,服务器端的clone。clone会默认添加origin关联,upstream的关联关系需要手动添加。

git的远程操作默认的仓库名为origin,如果对其他仓库进行操作,需要指定仓库名。

 git pull = git pull origin master # 缺省情况下,默认为origin
 git pull upstream master # 对其他仓库操作,需要指定

upstream提出的意义,一方面对于github上的repo,除非被声明为contributor,否则是没有push权限的,此时只有拉取代码的权限,因此通过拉取最新代码完成本地合并后,push到自己的origin仓库,再提出PR。另一方面,在团队开发中,需要对代码有个审核的过程,通过PR操作而非直接的push,可实现团队内部的代码审核。

总结下来:

(1)如果是 upstream repo,你只可以拉取最新代码(即 git fetch ),从而保证你本地的仓库与源仓库同步

(2)如果是 origin repo,就是你自己的repo(自己创建的,或者 fork 的项目)你可以做任何推拉操作(pull and push)

(3)你可以通过 pull request 向 upstream repo 贡献代码

3.抓取与合并操作

(1)远程端仓库克隆到本地

git clone 远程仓库地址   # 默认只能看的到master分支
git clone 远程仓库地址 本地仓库名字  # 完成本地仓库重命名(默认"远程仓库文件夹名-master")
git checkout -b dev origin/dev # 创建远程origin的dev分⽀到本地
git clone -b  分支名 远程仓库地址 # 该方法是直接克隆远程仓库的分支到本地

(2)抓取与合并

将本地仓库与远程仓库最新的代码合并包括两个过程,拉取最新代码与最新代码与本地代码合并。

拉取最新代码的命令是git fetch ,将拉取的代码与本地代码合并的命令有两种git merge和git rebase( 区别见git fetch和git rebase )。

git pull = git fetch + git merge,该命令会存在git merge引起的一些不友好的问题,所以推荐大家使用git fetch+ git rebase的方式,这会让你的提交记录非常的清爽,干净。

git fetch
git rebase
解决冲突
git add 冲突文件
git rebase --continue # 继续尝试合并
git push

如果git pull提⽰“no tracking information”,则说明本地分⽀和远程分⽀的链接关系没有创建,⽤命令git branch --set-upstream branch-name origin/branch-name。然后再进行git pull,合并,再提交。

4.推送操作

推送本地仓库内容至远程仓库(最常用命令),git push -u origin master

-u选项用于指定一个默认远程仓库,第一次push到origin时加上该参数,后续可以省略

上述命令的完整形式是:git push <远程仓库名> <本地分支名>:<远程分支名>

注意:这里的:前后是必须没有空格的,分支推送顺序的写法是<来源地>:<目的地>

a.如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。(最常用形式)。

b.如果省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。git push origin :master等同于git push origin --delete master.

c.如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。git push origin.将当前分支推送到origin远程仓库对应分支。

d.如果当前分支只有一个追踪分支,那么主机名都可以省略。git push.

参考资料:

廖雪峰:Git教程

阮一峰:读懂diff

onestark: Git:git diff 命令详解

git push -u origin master和git push <远程主机名> <本地分支名>:<远程分支名>作用

github中origin和upstream的区别

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐