git工具

注:本笔记全然参考廖雪峰老师的git教学网站所记,关于更详细的教程请参考廖雪峰的官方网站

 

Git是一种分布式版本控制系统

版本控制系统分集中式和分布式。

        集中式版本控制系统版本库存放于中央服务器,先从中央服务器取得最新版本,改动完毕后再送回中央服务器,而集中式版本控制系统的最大弊端在于联网才能工作。

        分布式版本控制系统没有中央服务器,每个人都有一个完整的版本库,因此工作时无需联网。而如果两个人工作在同一个文件,可以把各自的修改部分推送给对方,即可互相知道对方做出了哪些更改。

        相较于集中式版本控制系统,分布式版本控制系统安全性很高,每个人电脑都有完整的版本库,而集中式版本控制系统的中央服务器如果出现问题,后果要严重许多。其实分布式版本控制系统也有充当中央服务器的电脑,服务器的作用主要是方便大家的修改,但是没有它并不会有多大的问题

在安装完毕git之后,还需要最后的设置:

$git config --global user.name "name"
$git config --global user.email "email@example.com"

版本库

版本库即为仓库,仓库的所有文件都可以被Git管理,每个文件的修改、删除都会被Git跟踪。

# 通过git init命令可以将这个目录变成git可以管理的仓库
$git init

仓库中一般包含.git目录,目录默认隐藏,可以使用ls -ah命令查看。

将文件添加到版本库

所有的版本控制系统,其实只能跟踪文本文件的改动,txt、html、程序代码等。

对于文本文件,版本控制系统可以显示每次的改动细节

而图片、视频这些二进制文件,没法跟踪文件的变化只能知道文件大小的变动(Micresoft的word即为二进制文件)

将一个文件添加到git仓库只需要两步:

# 将文件添加到仓库
$git add readme.txt

# 将文件提交到仓库,-m后面是提交说明
$git commit -m "readme file"

可以一次性add多个文件,然后依次commit全部提交。

如果我们提交文件后,继续修改了文件,我们可以执行git status查看结果

$git status

git status可以查看当前仓库状态,比如修改后尚未提交的文件

$git diff

git diff可以查看到具体修改了哪些内容(difference)

版本回退

当文本文档已经被多次修改了,我们可以使用git log查看

$git log

git log可以查看从最近到最远的提交日志

如果觉得输出信息过于冗杂

# 输出日志,每个日志仅一行
$ git log --pretty=oneline


1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
# 回退至上个版本
$git reset --hard HEAD^

# 回退至上上版本
$git reset --hard HEAD^^

# 往上一百个版本
$git reset --hard HEAD~100

# 更新至某个版本号
$git reset --hard 版本号

如果忘记了想要更新至的版本号,可以使用git reflog查看每一次执行的命令

工作区和暂存区

工作区中的.git隐藏目录不算是工作区,而是git的版本库

git的版本库中最重要的便是stage的暂存区,创建的第一个分支master和指向master的指针HEAD

当执行git add命令后,文件会存放在暂存区保管等待提交。

管理修改

Git跟踪并管理的是修改,而非文件。

如果希望将初始文件和修改后的文件都提交,需要执行以下顺序

$git add readme.txt

# 修改

$git add readme.txt

$git commit -m ''

撤销修改

$git checkout -- file

将文件file在工作区的修改全部撤销。
1.file自修改后还没有放在暂存区,撤销修改即可以回到和版本库一样
2.file已经添加到暂存区后,又做了修改,撤销修改即回到添加到暂存区后的状态

也就是说,回到最近一次git commit或是git add时的状态。

如果是修改之后加入了暂存区,并没有提交:

$git reset HEAD readme.txt

可以将暂存区的修改撤销掉,重新放回工作区。

$git checkout -- readme.txt

继而执行checkout丢弃工作区的修改。

删除文件

通常我们执行删除命令

$rm readme.txt

当删除文件后,工作区和版本库不一致 ,执行git status可以查看哪些文件被删除了

如果我们需要从版本库中删除文件,则

执行命令

$git rm readme.txt

$git commit -m ""

版本库中文件即被删除

远程仓库

由于本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:

1.创建SSH Key

$ ssh-keygen -t rsa -C "youremail@example.com"

此时,可以在用户主目录中找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的密钥对,其中,id_rsa是私钥,私钥不可泄露,id_rsa.pub是公钥。

2.在GitHub的SSH Key页面在Key文本框中粘贴id_rsa.pub文件内的内容。

添加远程仓库

# origin即为远程仓库的名字
$ git remote add origin url
$git push -u origin master

第一次添加远程仓库后,由于远程仓库为空需要加上-u参数

git不但会把本地的master分支内容推送到远程仓库的master分支,还会将本地master分支和远程master分支关联起来。

删除远程仓库

# 查看远程仓库信息
$ git remote -v

# 根据仓库名字删除
$git remote rm name

 从远程库克隆

$ git clone ssh-url

 创建与合并分支

在git中,有个主分支即master分支,HEAD指向当前的分支,然后当前分支指向提交。

例如当我们创建新的分支slave时,HEAD会转而指向slave,而salve指向着和master指向相同的提交。

当我们进行新的提交时,slave指针会向前移动,而master指针不变。

如果我们在slave分支上的任务完成了,想把slave合并到分支master上面,可以让master直接指向slave的当前的提交。

合并后,甚至可以删掉slave指针。

# 创建slave分支,切换到slave分支
$git checkout -b slave

# 等同于
$git branch slave
$git checkout slave
# 查看当前分支
$git branch

git branch会列出所有分支,当前分支加*

 如果在slave上新建文件并作出提交,在master分支上不会出现,需要合并分支才可以见到。

# 将slave分支合并到master分支
$git merge slave

下面就是删除分支了

$git branch -d slave

实际上,切换分支使用switch更加科学:

# 创建并切换到新的分支
$git switch -c slave

# 直接切换到slave分支
$git switch slave

解决冲突

当两个分支修改了同一个文件时,合并分支会发生冲突

此时执行git status可以看到冲突的文件

查看文件的内容时可以看到之间不同分支的差异,我们可以做出更改后继而上传提交。

此时执行git log命令可以查看合并情况。

Bug分支

当软件的开发出现bug时,我们可以新建一个临时分支来修复bug,修复后合并分支,然后删除临时分支。

但是,如果当前的工作还没有完成,而且工作需要一天来完成,而bug需要两小时来修复。

# git提供了stash的功能,可以存储当前的工作现场,等恢复现场后继续工作
$git stash
Saved working directory and index state WIP on dev: f52c633 add merge

然后切换到需要修复bug的分支,修复bug,提交,合并分支,删除分支

继而回到工作分支继续干活。

$git stash list
stash@{0}: WIP on dev: f52c633 add merge

下面有两种恢复工作现场的办法:

# 恢复工作现场后,stash内容不删除
$git stash apply stash@{0}

# 恢复工作现场的同时删除stash
$git stash pop stash@{0}

此时,会想到当前工作分支是从master分支分出来的,如果master存在bug,那么当前工作分支也会存在bug。

那么,如何在当前分支修复同样的bug呢?

其实,只需要将在master上提交所做的修改复制到当前工作分支即可,我们只需要复制该提交所需要的修改。

$git cherry-pick 提交号 

Feature分支

当我们对新的分支创建了新的功能。

$git switch -c feature-vulcan
Switched to a new branch 'feature-vulcan'

# 开发完毕

$git add vulcan.py

$git status
On branch feature-vulcan
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   vulcan.py

$git commit -m "add feature vulcan"
[feature-vulcan 287773e] add feature vulcan
 1 file changed, 2 insertions(+)
 create mode 100644 vulcan.py

# 切回主分支准备合并
$git switch dev

但是此时因为某些原因,需要将新建分支删除

$git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.

# 强制删除
$git branch -D feature-vulcan
Deleted branch feature-vulcan (was 287773e)

多人协作

# 查看远程仓库信息
$git remote

# 显示更详细的信息
$git remote -v

# 将分支上的本地提交推送到远程仓库,可以指定本地分支
$git push origin master

#master分支是主分支,因此要时刻与远程同步
#dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步
#bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug
#feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

多人协作时,大家都会往master和dev分支上推送各自的修改。

当我们从远程仓库clone时,默认情况下,只能看到本地的master分支。

# 现在如果我们想要在dev分支开发,需要创建origin的dev分支到本地才可以
$git checkout -b dev origin/dev

现在,可以在dev上继续修稿,然后将dev分支push到远程。

如果我修改了dev分支的文件,而碰巧别人对同样的文件做了修改,这时候推送,会遇到问题:

$git push origin dev
To github.com:michaelliao/learngit.git
 ! [rejected]        dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

解决方法:我们呢需要先git pull把最新的提交从origin/dev抓下来,然后本地合并,解决冲突,再推送。

$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

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

此时发现,git pull失败了,因为我们没有指定本地的dev分支和远程origin/dev分支的链接。

# 设置dev和origin/dev的链接
$git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.

然后再git pull,合并,解决冲突即可。

标签管理

切换到需要打标签的分支上

# 打标签
$git tag v1.0
# 查看所有标签
$git tag

默认来说,标签是打在最新提交的commit上,如果忘记打标签了

# 找出历史提交的commit id
$git log --pretty=oneline --abbrev-commit

# 打标签
$git tag v0.9 f52c633

# 打带说明的标签,-a指定标签名,-m指定说明文字
$git tag -a v1.0 -m "说明"

# 查看标签信息
$git show <tagname>

# 创建的标签都只存储在本地,不会自动推送到远程。
# 删除标签
$git tag -d <tagname>

# 将标签推送至远程仓库
$git push <remote name> <tagname>

# 推送所有的尚未推送的本地标签
$git push <remote name> --tags

# 删除远程标签
$git tag -d <tagname>
$git push origin :refs/tags/<tagname>

 自定义Git

# 让Git显示颜色,会让命令输出看起来更醒目
$git config --global color.ui true

忽略特殊文件

如果在git工作目录中存在必须存在,又无需提交的配置文件。
可以在git的工作区根目录下创建.gitignore文件,将要忽略的文件名填进去,git会自动忽略这些文件。

忽略文件的原则:
        1.系统自动生成的文件,如缩略图等
        2.编译生成中间文件
        3.带有敏感信息的配置文件

# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class

# 不排除.gitignore和App.class:
!.gitignore
!App.class

配置别名

# commit设为别名cm
$git config --global alias.cm commit

# 撤销暂存区修改:git reset HEAD file(两个字段用单引号连接)
$git config --global alias.unstage 'reset HEAD'

其中,配置文件

        每个仓库的git配置都放在.git/config文件中。
        当前用户的git配置文件放在用户主目录下的.gitconfig文件中。

搭建Git服务器

        GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。

        搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。

# 安装git
$sudo apt-get install git

# 创建git用户,用来运行git服务
$sudo adduser git

# 创建证书登录
# 收集需要登录的用户的公钥,即id_rsa.pub文件,将所有公钥导入/home/git/authorized_keys

# 初始化git仓库,选定目录作为git仓库,假定是/src/sample.git,在/src目录下输入
$sudo git init --bare sample.git
# 此时git会创建裸仓库,裸仓库没有工作区,因为服务器上的git仓库纯粹为了共享,所以不让用户直接登录到
# 服务器上改工作,并且服务器上的git仓库通常以.git结尾,把owner改为git:
$sudo chown -R git:git sample.git

# 禁用shell登录
# 出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成
# 将
git:x:1001:1001:,,,:/home/git:/bin/bash
# 改为
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
# 这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一 # 登陆自动退出

# 克隆远程仓库
$git clone url


版权声明:本文为m0_38131863原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。