git学习之阅读progit的读书笔记(1)

1 集中式 vs 分布式版本控制系统

如何有效对项目版本管理?如何有效团队协同开发? 版本控制系统。
从集中式 发展到 分布式:
集中式:版本库是集中放在中央服务器的,开发从中央服务器获取,必须联网开发
分布式:取消了中央服务器的概念,每个开发人员的电脑就是一个完整的版本库,可脱网开发,效率高更安全
注:在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

2 git文件状态和三个工作区域

  1. 文件状态:
    未跟踪的文件的改动不受到git的版本控制。
    已跟踪的文件,即被纳入版本控制的文件:又分为未修改(unmodified)、已修改(modified)、已暂存(staged)三种状态。
    说明:一般从项目中clone下来的文件都是追踪状态,但是你新建了一些文件就是未被追踪状态,想要被git管理,就add到暂存区被管理
  2. 工作目录(本地修改 modified状态)——> add 到暂存区 ——> commit提交到.git版本库

3 git开发工作流程

3.1 安装git并设置配置信息

设置用户信息:
$ git config --global user.name “John Doe”
$ git config --global user.email johndoe@example.com
查看当前信息
$ git config --list
查看某一项信息
$ git config user.name

3.2 git初始化本地仓库

3.2.1 从0建立仓库

$ git init
$ git add *.c
$ git add LICENSE
$ git commit -m ‘initial project version’

3.2.2 合作别人已经开发了的仓库

$ git clone https://github.com/libgit2/libgit2
或者 自定义仓库名称
$ git clone https://github.com/libgit2/libgit2 mylibgit
以上使用https协议,也可以ssh协议

3.3 查看仓库状态

$ git status

3.4 查看尚未暂存的具体改动

git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。

4 关于暂存态的一些操作

4.1 改动提交到本地git版本库中

$ git commit -m “Story 182: Fix benchmarks for speed”

4.2 跳过暂存区直接提交到本地版本库 -a参数

$ git commit -am ‘added new benchmarks’

4.3 移除文件

从暂存区中移除文件并删除本地文件

rm来删除文件,仅仅是删除了物理文件,没有将其从 git 的记录中剔除;
$ rm PROJECTS.md
git rm来删除文件,同时还会将这个删除操作记录下来;
$ git rm PROJECTS.md

从本地版本库中移除文件并删除本地文件

git rm -f

删除git管理状态但是保留物理磁盘上的该文件

从索引中删除文件。但是本地文件还存在,只是不希望这个文件被版本控制。
git rm --cached 文件名

应用案例:
忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时

4.4 文件移动

$ git mv file_from file_to

4.5 查看历史提交记录

git log

4.6 暂存区回到本地修改状态

git reset HEAD filename

4.7 撤销对本地文件的修改

git checkout – filename

5 远程仓库的使用

5.1 查看本地仓库的关联的远程仓库

git remote -v(同时显示仓库的url)

5.2 添加远程仓库

git remote add pb https://github.com/paulboone/ticgit 理解:给git仓库起别名,下次直接使用pb来代替这个url
git fetch pb

5.3 从远程仓库拉取代码

$ git fetch [remote-name]
注意 git clone 、 git fetch、 git pull的区别
git clone顾名思义就是将其他仓库克隆到本地,包括被clone仓库的版本变化。clone操作是一个从无到有的克隆操作,再次强调不需要git init初始化。(初次开发)
git fetch更新远程代码到本地仓库,但是不合并。
git pull是拉取远程分支更新到本地仓库的操作。git pull是相当于从远程仓库获取最新版本,然后再与本地分支merge(合并)。git pull = git fetch + git merge

方法一
$ git fetch origin master #从远程的origin仓库的master分支下载代码到本地的origin maste
$ git log -p master… origin/master #比较本地的仓库和远程参考的区别
$ git merge origin/master #把远程下载下来的代码合并到本地仓库,远程的和本地的合并

将远程主机origin的master分支拉取过来,与本地的branchtest分支合并。
$ git pull origin master:branchtest

5.4 推送到远程分支

git push [remote-name] [branchname]
$ git push origin master

5.5 查看远程分支

git remote show [remote-name]
git remote show origin

6 打标签

git可以给历史中的某一个提交打上标签

6.1 列出标签

git tag

6.2 创建标签

git使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。
一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用。
然而,附注标签是存储在 Git 数据库中的一个完整对象。 它们是可以被校验的;其中包含打标签者的名字、电子
邮件地址、日期时间;还有一个标签信息;并且可以使用 GNU Privacy Guard (GPG)签名与验证。 通常建议
创建附注标签,这样你可以拥有以上所有信息;但是如果你只是想用一个临时的标签,或者因为某些原因不想要
保存那些信息,轻量标签也是可用的。
附注标签
$ git tag -a v1.4 -m ‘my version 1.4’
$ git tag
v0.1
v1.3
v1.4
$ git show v1.4

7 本地分支【分支的概念可以理解为建立指针的相关操作】

鼓励频繁的创建和合并分支
git保存的是一系列不同时刻的文件快照

7.1 master分支

git的默认分支是master分支
Git 的 “master” 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每
一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动
它。

7.2 git创建分支的内部原理

默认是master分支,当我们git branch branchname创建了一个新分支,此时新分支和master分支是指向同一个项目快照的
可以通过git log --online --decorate查看当前分支所指向的对象,注意有个HEAD指针是专门指向当前分支的,可以理解为当前分支的别名。

7.3 创建分支

$ git checkout testing
这样HEAD就会从master分支指向testing,表示当前所处分支

$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

7.4 分支的新建与合并

案例背景:
开发需求新建了一个分支,正在开发需求。
然后出现紧急任务,切回线上分支,再新建一个分支来修改bug,改完bug回合到主线上
然后再切回当初的需求分支继续开发。

开发一个新需求:此时创建分支,并切换到该分支进行开发
$ git checkout -b iss53
Switched to a new branch “iss53”
等价于
$ git branch iss53
$ git checkout iss53
此时你在iss53上分支继续开发,HEAD指向iss53,iss53分支在不断向前推进

此时项目出现了一个紧急bug,需要去修改
git的优势:1 不用将bug和新需求的开发混在一起 2 不用回退我们之前的开发,再修改bug

切回master分支(在切换分支之前要保持当前分支的干净状态:保存进度stashing,修补提交commit amending)
$ git checkout master
Switched to branch ‘master’
建立紧急问题的处理分支,进行bug修复,提交到本地版本库里
$ git checkout -b hotfix
Switched to a new branch ‘hotfix’
$ vim index.html
$ git commit -a -m ‘fixed the broken email address’
[hotfix 1fb7853] fixed the broken email address
1 file changed, 2 insertions(+)

提交后,切换到master分支,来回合我们hotfix的bug分支
$ git checkout master
$ git merge hotfix
Updating f42c576…3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
master指针移动到了指向了hotfix指针的
此时bug修改已经在master分支上了,我们可以删除这个hotfix分支了
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).

此时应该切换之前的开发分支iss53,继续进行开发
注意:之前对bug修改的代码并没有体现在你现在修改的分支上,方法:
1. git merge master 命令将 master 分支合并入 iss53 分支
或者
2. iss53完成开发后合并到master上
这里以方法二进行举例:先不合并修改的,继续在该分支完成开发工作
$ git checkout iss53
Switched to branch “iss53”
$ vim index.html
$ git commit -a -m ‘finished the new footer [issue 53]’
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)

将开发分支上的代码回合到主线上去
$ git checkout master
Switched to branch ‘master’
$ git merge iss53
Merge made by the ‘recursive’ strategy.
index.html | 1 +
1 file changed, 1 insertion(+)

  1. 拓展(关于分支是如何合并的)
    当master分支是iss53的直接祖先,那么合并就只要简单的移动master指针到iss53上,然后删除iss53就可以完成合并了
    当master分支不是iss53的直接祖先,而是在共同祖先之后就分叉了,此时git会创建一个新的提交指针进行三方(master快照、共同祖先快照、iss53快照)的合并,并让master指向它。

合并结束之后就可以删除iss53分支了
$ git branch -d iss53

7.5 合并分支冲突情况

案例:在刚才过程中,如果你修改的文件内容在hotfix分支和iss53分支上有重叠,那么当hotfix合并到主线上后,再进行iss53合并到主线就会产生冲突,究竟应该按照谁的呢?
这时候你试图合并就会出现:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
查看冲突状态
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run “git commit”)
Unmerged paths:
(use “git add …” to mark resolution)
both modified: index.html
no changes added to commit (use “git add” and/or “git commit -a”)

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出
到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 =======
和相关开发人员确认后代码,以及让自己的代码的功能可行,将冲突部分代码进行修改,修改完成后git add到暂存区,然后commit提交即可。

7.6 分支管理

git branch查看所有分支的列表

$ git branch
  iss53
* master
  testing
* 表示当前HEAD指针指向的当前的分支,意味着每次提交master分支都会继续向前,
git branch --merged:可以过滤当前已经合并过的分支
$ git branch --merged
  iss53
* master
已经合并了 iss53 分支,。 在这个列表中分支名字前没有 * 号的分支通常可以使用 git branch -d 删除掉

查看所有包含未合并工作的分支,可以运行 git branch --no-merged:
尝试使用 git branch -d 命令删除它时会失败

7.7 分支开发工作流

稳定分支的指针总是在提交历史中落后一大截,而前沿分支的指针往往比较靠前。
我们一般是在一个分支稳定后,再合入一个更加稳定的分支。
我们可以自定义很多特性分支,利用各个分支来开发各个需求。有用的分支就合并到稳定的master分支,不用的分支就可以丢弃。

以上都是在git的本地版本库中的操作,没有和远程服务器的交互。

8 远程分支

8.1 基础概念(注意区别本地分支与远程分支的概念)

远程仓库引用指向远程仓库的所有分支状态的书签,以(remote)/(branch)形式命名。
案例:git clone 后
Git 的 clone 命令会为你自动将其命名为 origin,拉取它的所有数据,创建一个指向它的 master 分支的指针,
并且在本地将其命名为 origin/master。 Git 也会给你一个与 origin 的 master分支在指向同一个地方的本地 master 分支。
这样就会产生两个指针,一个指针用来维护对接远程仓库的origin/master,一个指针是本地的master。我们开发的时候master会自动前移,一般origin/master是不动它的
当然在某个时刻远程服务器更新了master,我们可以git fetch origin来更新本地的origin/master上的代码和指针,但是本地master是不会动的

8.2 将本地分支推送到远程仓库分支

git push origin serverfix:serverfix,
推送本地的 serverfix 分支,将其作为远程仓库的 serverfix 分支
也可以省略,将当前的本地分支直接推送到远程分支serverfix。【git push origin serverfix】
如果并不想让远程仓库上的分支叫做 serverfix,可以运行 git push origin serverfix:awesomebranch 来将本地的 serverfix 分支推送到远程仓库上的 awesomebranch分支。

8.3 从远程仓库分支获取到本地

从服务器上抓取时,就会在本地自动生成一个远程分支origin/serverfix,,指向服务器的serverfix 分支的引用。
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit

  • [new branch] serverfix -> origin/serverfix

注意本地只会有一个不可以修改的 origin/serverfix 指针,指向服务器的那个分支,本地不会自动创建本地的serverfix分支。
可以合并到我们当前的开发分支,如git merge origin/serverfix 将这些工作合并到当前所在的分支。
或者
自己本地创建一个serverfix分支,并添加追踪到远程的origin/serverfix分支上,如
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch ‘serverfix’

8.4 如何关联本地分支与远程分支(追踪分支)

从一个远程跟踪分支检出一个本地分支会自动创建所谓的 “跟踪分支”,跟踪分支是与远程分支有直接关系的本地分支。 如果在一个跟踪分支上输入 git pull,Git 能自动地
识别去哪个服务器上抓取、合并到哪个分支。

情况1:我们克隆了一个仓库
通常会自动地创建一个跟踪 origin/master 的 master 分支
当然也可以自定义追踪分支,如git checkout -b [branch] [remotename]/[branch],可自定义本地的追踪分支的名称。
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch ‘sf’
或者直接快捷方式分支
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch ‘serverfix’
或者在某一时刻想要修改追踪的上游分支,可以在任意时间使用 -u 或 --set-upstream-to 选项运行 git branch 来显式地设置。
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.

情况2:查看设置的追踪分支
$ 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

这里可以看到 iss53 分支正在跟踪 origin/iss53 并且 “ahead” 是 2,意味着本地有两个提交还没有推送
到服务器上。 也能看到 master 分支正在跟踪 origin/master 分支并且是最新的。 接下来可以看到
serverfix 分支正在跟踪 teamone 服务器上的 server-fix-good 分支并且领先 3 落后
1,意味着服务器上有一次提交还没有合并入同时本地有三次提交还没有推送。 最后看到 testing 分支并没有
跟踪任何远程分支。
需要重点注意的一点是这些数字的值来自于你从每个服务器上最后一次抓取的数据。 这个命令并没有连接服务
器,它只会告诉你关于本地缓存的服务器数据。 如果想要统计最新的领先与落后数字,需要在运行此命令前抓
取所有的远程仓库。 可以像这样做:$ git fetch --all; git branch -vv

8.5 拉取远程分支

当 git fetch 命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容。 它只会获取数据然
后让你自己合并。 然而,有一个命令叫作 git pull 在大多数情况下它的含义是一个 git fetch 紧接着一个
git merge 命令。 如果有一个像之前章节中演示的设置好的跟踪分支,不管它是显式地设置还是通过 clone
或 checkout 命令为你创建的,git pull 都会查找当前分支所跟踪的服务器与分支,从服务器上抓取数据然
后尝试合并入那个远程分支。
由于 git pull 的魔法经常令人困惑所以通常单独显式地使用 fetch 与 merge 命令会更好一些。

8.6 删除远程分支

如果远程开发分支的任务已经完成,然后合并到了远程开发的主线上了,那么就可以从服务器上删除这个远程开发分支。
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit

  • [deleted] serverfix
    基本上这个命令做的只是从服务器上移除这个指针。 Git 服务器通常会保留数据一段时间直到垃圾回收运行,所
    以如果不小心删除掉了,通常是很容易恢复的。

9 变基

在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase。
案例:本地两个分支进行合并,可以直接用merge对三方的快照进行合并
也可以通过变基rebase来实现,就是将某一分支上的所有修改移动到另一个分支上。
如将experitment分支上的代码合并到master上
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it…
Applying: added staged command
切换到experiment分支上,将分支上的所有到共同祖先上的修改存储为临时文件,以master分支为基础进行合并
再切回到master分支上,进行合并
$ git checkout master
$ git merge experiment

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值