Git 与 SVN 区别

Git是一个开源的分布式版本控制系统,用于麻利高效地解决任何或小或大的我的项目。Git 是 Linus Torvalds 为了帮忙治理 Linux 内核开发而开发的一个开放源码的版本控制软件。Git 与罕用的版本控制工具 CVS, Subversion 等不同,它采纳了分布式版本库的形式,不用服务器端软件反对。

GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。如果你是一个具备应用SVN背景的人,你须要做肯定的思维转换,来适应GIT提供的一些概念和特色。Git 与 SVN 区别点:
1、GIT是分布式的,SVN不是:这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最外围的区别。
2、GIT把内容按元数据形式存储,而SVN是按文件:所有的资源控制系统都是把文件的元信息暗藏在一个相似.svn,.cvs等的文件夹里。
3、GIT分支和SVN的分支不同:分支在SVN中一点不特地,就是版本库中的另外的一个目录。
4、GIT没有一个全局的版本号,而SVN有:目前为止这是跟SVN相比GIT短少的最大的一个特色。
5、GIT的内容完整性要优于SVN:GIT的内容存储应用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时升高对版本库的毁坏。

Git工作原理

Git工作流程能够分一下步骤:

  • 克隆 Git 资源作为工作目录;
  • 在克隆的资源上增加或批改文件;
  • 如果其他人批改了,你能够更新资源;
  • 在提交前查看批改。提交批改;
  • 在批改实现后,如果发现错误,能够撤回提交并再次批改并提交;

Git 工作区、暂存区和版本库:

  • 工作区:就是你在电脑里能看到的目录。
  • 暂存区:英文叫stage, 或index。个别寄存在"git目录"下的index文件(.git/index)中,所以咱们把暂存区有时也叫作索引(index)。
  • 版本库:工作区有一个暗藏目录.git,这个不算工作区,而是Git的版本库。

常见操作

全局配置用户信息

git config --global user.name "smyhvae"git config --global user.email "smyhvae@163.com"

Git 创立仓库

git init repository

如果当前目录下有几个文件想要纳入版本控制,须要先用 git add 命令通知 Git 开始对这些文件进行跟踪,而后提交:

$ git add *.c$ git add README$ git commit -m 'initial project version'

从现有仓库克隆

$ git clone git://github.com/test/test.git

Git基本操作命令

git init
创立我的项目命令,在目录中创立新的 Git 仓库。 你能够在任何时候、任何目录中这么做,齐全是本地化的。在目录中执行 git init,就能够创立一个 Git 仓库。

$ mkdir test$ cd test$ git init

git clone
应用 git clone 拷贝一个 Git 仓库到本地,让本人可能查看该我的项目,或者进行批改。

$ git clone git://github.com/test/test.git

git push
其作用是将本地分支的更新推送到近程主机

$ git push <近程主机名> <本地分支名>:<近程分支名>

git pull
其作用是将近程主机更新到本地分支

$ git pull <近程主机名> <本地分支名>:<近程分支名>

git add
git add 命令可将该文件增加到缓存,如咱们增加以下两个文件:

$ touch README$ touch hello.php$ lsREADME      hello.php$ git status -s?? README?? hello.php$ 

git status
命令用于查看我的项目的以后状态

$ git add README hello.php $ git status -sA  READMEA  hello.php$ 

git diff
git diff 命令显示已写入缓存与已批改但尚未写入缓存的改变的区别。git diff 有两个次要的利用场景:
尚未缓存的改变:git diff
查看已缓存的改变: git diff --cached
查看已缓存的与未缓存的所有改变:git diff HEAD
显示摘要而非整个 diff:git diff --stat

$ git status -sA  READMEAM hello.php$ git diffdiff --git a/hello.php b/hello.php

git commit

应用 git add 命令将想要快照的内容写入了缓存, 而执行 git commit 记录缓存区的快照。Git 为你的每一个提交都记录你的名字与电子邮箱地址,所以第一步须要配置用户名和邮箱地址。

$ git config --global user.name 'admin'$ git config --global user.email admin@qq.com$ git add hello.php$ git status -sA  READMEA  hello.php$ git commit -m 'test comment from test.cn'[master (root-commit) 85fc7e7] test comment from test.cn 2 files changed, 4 insertions(+) create mode 100644 README create mode 100644 hello.php

当初咱们曾经记录了快照。如果咱们再执行 git status:

$ git status# On branch masternothing to commit (working directory clean)

git log
查看历史提交记录

$ git logcommit 88afe0e02adcdfea6844bb627de97da21eb10af1Merge: 14b4dca d7e7346Author: adminDate:   Sun Mar 1 15:03:42 2020 +0800    Merge branch 'change_site'        Conflicts:        test.txtcommit 14b4dcadbdc847207651d5a9fae0d315057f346eAuthor: adminDate:   Sun Mar 1 14:53:15 2015 +0800

git tag
能够应用 git tag 给打上标签

git reset HEAD
命令用于勾销缓存已缓存的内容。

$ git status -s M README M hello.php$ git add .$ git status -sM  READMEM  hello.pp$ git reset HEAD -- hello.php Unstaged changes after reset:M hello.php$ git status -sM  README M hello.php

git rm
将文件从缓存区中移除。

$ git rm hello.php rm 'hello.php'$ lsREADME

git mv
命令做得所有事件就是 git rm --cached, 重命名磁盘上的文件,而后再执行 git add 把新文件增加到缓存区。因而,尽管有 git mv 命令,但它有点多余 。

分支的合并

场景:基于master分支的代码,开发一个新的个性

如果你间接在master分支上开发这个新个性,是不好的,万一你在开发个性1的时候,领导忽然又要叫你去开发个性2,就不好解决了。难道开发的两个个性都提交到master?一会儿提交个性1的commit,一会儿提交个性2的commit?这会导致commit记录很凌乱。

所以,我给你的倡议做法是:给每个个性都独自建一个的新的分支。

比如说,我专门给个性1建一个分支feature_item_recommend。具体做法如下:

(1)基于master分支,创立一个新的分支,起名为feature_item_recommend

$ git checkout -b feature_item_recommendSwitched to a new branch 'feature_item_recommend'

下面这行命令,相当于:

$ git branch feature_item_recommend    // 创立新的分支$ git checkout feature_item_recommend  //切换到新的分支

(2)在新的分支feature_item_recommend上,实现开发工作,并 commit 、push。

(3)将分支feature_item_recommend上的开发进度合并到master分支:

$ git checkout master  //切换到master分支$ git merge feature_item_recommend    //将分支 feature_item_recommend 的开发进度合并到 master 分支

合并之后,master分支和feature_item_recommend分支会指向同一个地位。

(3)删除分支feature_item_recommend

既然 个性1 开发完了,也释怀地提交到master了,那咱们就能够将这个分支删除了。
git branch -d feature_item_recommend

留神,咱们以后是处于master分支的地位,来删除feature_item_recommend分支。如果以后是处于feature_item_recommend分支,是没方法删除它本人的。

同理,当我转身去开发个性2的时候,也是采纳同样的步骤。

合并分支时,如果存在分叉

比如说下面这张图中,最早的时候,master分支是位于C2节点。我基于C2节点,new出一个新的分支iss53,我在iss53上提交了好几个commit。

当初,我筹备把iss53上的几个commit合并到master上,此时发现,master分支曾经后退到C4了。那该怎么合并呢?

合并的命令依然是:

$ git checkout master$ git merge iss53

解释

这次合并的实现,并不同于简略的并入形式。这一次,我的开发历史是从更早的中央开始分叉的。

因为以后 master 分支所指向的commit (C4)并非想要并入分支(iss53)的间接先人,Git 不得不进行一些解决。就此例而言,Git 会用两个分支的末端(C4 和C5)和它们的独特先人(C2)进行一次简略的三方合并计算。

Git 没有简略地把分支指针右移,而是对三方合并的后果作一新的快照,并主动创立一个指向它的commit(C6)(如下图所示)。咱们把这个非凡的commit 称作合并提交(mergecommit),因为它的先人不止一个。

值得一提的是Git 能够本人裁决哪个独特先人才是最佳合并根底;这和CVS 或Subversion(1.5 当前的版本)不同,它们须要开发者手工指定合并根底。所以此个性让Git 的合并操作比其余零碎都要简略不少。

解决合并时产生的抵触

如果 feature1和feature2批改的是同一个文件中代码的同一个地位,那么,把feature1合并到feature2时,就会产生抵触。这个抵触须要人工解决。步骤如下:

(1)手动批改文件:手动批改抵触的那个文件,决定到底要用哪个分支的代码。

(2)git add:解决好抵触后,输出git status,会提醒Unmerged paths。这个时候,输出git add即可,示意:批改抵触胜利,退出暂存区

(3)git commit 提交。

而后,咱们能够持续把 feature1 分支合并到 master分支,最初删除feature1、feature2。

留神:两个分支的同一个文件的不同中央合并时,git会主动合并,不会产生抵触。

比方分支feture1对index.html原来的第二行之前退出了一段代码。
分支feature2对index.html在原来的最初一行的前面退出了一段代码。
这个时候在对两个分支合并,git不会产生抵触,因为两个分支是批改同一文件的不同地位。
git主动合并胜利。不论是git主动合并胜利,还是在人工解决抵触下合并胜利,提交之前,都要对代码进行测试。

日常操作积攒

批改明码(曲线救国)

网上查了很久,没找到答案。最终,在cld童鞋的提醒下,采取如下形式进行曲线救国。
# 设置以后仓库的用户名为空git config  user.name ""

而后,当咱们再输出git pull等命令行时,就会被要求从新输出新的账号密码。此时,明码就能够批改胜利了。最初,咱们还要输出如下命令,还原以后仓库的用户名:

git config user.name "smyhvae"

批改曾经push的某次commit的作者信息

曾经push的记录,如果要批改作者信息的话,只能 通过--force命令。

branch1的某个commit1合并到branch2当中

切换到branch2中,而后执行如下命令:

git cherry-pick commit1

20200118-批改GitHub已提交的用户名和邮箱

在执行./email.sh后,如果呈现permission denied的谬误,能够先执行chmod 777 email.sh,批改文件的权限。

20200520-将Git 我的项目迁徙到另一个仓库

咱们假如旧仓库的项目名称叫old-repository,新仓库的项目名称叫new-repository。操作如下:

(1)创立旧仓库的裸克隆:

git clone --bare https://github.com/exampleuser/old-repository.git

执行上述命令后,会在本地生成一个名叫 old-repository.git的文件夹。

(2)迁徙到新仓库:

cd old-repository.gitgit push --mirror https://github.com/exampleuser/new-repository.git

这样的话,我的项目就曾经迁徙到新仓库了。

留神,咱们不须要手动新建一个空的新仓库,当咱们执行上述命令之后,新仓库就曾经主动创立好了。

参考链接:

  • 复制仓库
  • Git 本地仓库和裸仓库

Git 服务器搭建

咱们将以 Centos 为例搭建 Git 服务器。

1、装置Git

$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel$ yum install git

创立一个git用户组和用户,用来运行git服务:

$ groupadd git$ adduser git -g git

2、创立证书登录
收集所有须要登录的用户的公钥,公钥位于id_rsa.pub文件中,把咱们的公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。如果没有该文件创建它:

$ cd /home/git/$ mkdir .ssh$ chmod 700 .ssh$ touch .ssh/authorized_keys$ chmod 600 .ssh/authorized_keys

3、初始化Git仓库
首先咱们选定一个目录作为Git仓库,假设是/home/gitrepo/hello.git,在/home/gitrepo目录下输出命令:

$ cd /home$ mkdir gitrepo$ chown git:git gitrepo/$ cd gitrepo$ git init --bare hello.gitInitialized empty Git repository in /home/gitrepo/hello.git/

以上命令Git创立一个空仓库,服务器上的Git仓库通常都以.git结尾。而后,把仓库所属用户改为git:

$ chown -R git:git w3cschoolcn.git

4、克隆仓库

$ git clone git@192.168.45.4:/home/gitrepo/w3cschoolcn.gitCloning into 'w3cschoolcn'...warning: You appear to have cloned an empty repository.Checking connectivity... done.

192.168.45.4 为 Git 所在服务器 ip ,你须要将其批改为你本人的 Git 服务 ip。这样咱们的 Git 服务器装置就实现了,接下来咱们能够禁用 git 用户通过shell登录,能够通过编辑/etc/passwd文件实现。找到相似上面的一行:

git:x:503:503::/home/git:/bin/bash改为:git:x:503:503::/home/git:/sbin/nologin

Git客户端举荐

TortoiseGit

对这只小乌龟预计没有开发人员会不意识,SVN的超宽泛应用也使得这个超好用的Svn客户端成了简直每个开发人员的桌面必备软件。小乌龟只提供Windows版本,提供中文版反对的,对于中国的开发者来说者相对是福音。

小乌龟的文件管理器右键菜单的操作形式对于老手来说十分的容易上手,而且容易了解。
TortoiseGit(git客户端工具)

Sublime Merge for Mac(git客户端工具)
领有简洁的界面,三向合并工具,弱小搜寻性能,语法突出显示等特点,Sublime Merge for Mac是一款Git客户端工具,实现了Sublime。与Sublime Text的制造商会面。一个疾速的用户界面,三向合并工具,并排差别,语法高亮等等。Stage Files,iSwiftHunks和Lines没有期待 – Sublime Merge真的十分十分快。

Sublime Merge for Mac(git客户端工具)

GitHub for Desktop

寰球开发人员交友俱乐部提供的弱小工具,功能完善,使用方便。对于应用GitHub的开发人员来说是十分便捷的工具。界面洁净,用起来十分棘手,下面的这条timeline十分丑陋,也能够间接提交PR。

惟一让我悲观的是GitHub for Desktop不带三方合并工具,你必须本人手动解决抵触才能够。– 收费
– 同时反对 Windows 和 Mac:对于须要常常在不同的操作系统间切换的开发人员来说十分不便。
– 丑陋的界面:作为每天盯着看的工具,颜值是十分重要的
– 反对Pull Request:间接从客户端提交PR,很不便
– Timeline 反对:间接在工夫线上显示每次提交的工夫点和大小
– 反对git LFS:存储大文件更加节俭空间和高效
– 不反对三方合并:须要借助第三方工具才行

Source Tree

SourceTree是老牌的Git GUI管理工具了,也号称是最好用的Git GUI工具。我的体验是的确弱小,功能丰富,基本操作和高级操作都设计得十分晦涩,适宜初学者上手。

这个工具很有特色的一个性能就是反对Git Flow,你能够一键创立Git Flow的工作流。Git Flow是十分高效的团队合作模型和流程,Git的一大特色就是灵便轻量的分支,但如何在本人的团队中用好这个性能来匹配本人的研发流程是个问题。内置Git Flow让那些不太熟悉的开发人员也能够很快上手,并且将研发的业务流程固化在工具中,能够说是十分贴心的设计。

Source Tree(git客户端工具)

SmartGit

商业用途免费, 个人用户收费:

举荐书籍

  • 《pro.git中文版》