Git 小记

介绍

Git是一个软件版本控制管理的一种机制和实现,类似的还有:SVN, Mercurial;更详细的可以参见维基百科的list of version control software 。

不同于SVN,Git是一种分布式的版本控制系统。最初是Linus Torvalds 为了用于管理Linux内核而在2005年开发的,2008年建立的Github网站则使得git系统日益流行。

代码托管网站

  • GitHub
  • GitLab
  • BitBucket
  • 码云Gitee.com (开源中国, CSDN)
  • 扣钉 Coding.net

Git基础

Git主要特点:

  • 分布式:每个主机上保存的仓库副本都有完整的记录
  • 快照记录而非差异比较:类似文件系统的方式,每次提交更新都是对全部文件制作一个快照并保存快照的缩影
  • 主要操作是本地执行

Git尽管是分布式的结构,但在团队协作中,通常会在服务器中建立一个仓库作为(准)中心。因此Git中存在远程仓库(比如在服务器中)和本地仓库(当前工作环境):

  • 远程仓库也叫上游仓库(upstream repostory),可以看做版本的最终状态。
  • 本地环境有四部分组成:工作区(workspace,程序和资源区域)、本地仓库(local repository,隐藏目录.git)、索引区(Index,也叫缓存区)、隐藏区(stash)。
    • 工作区中存放的实际操作的文本文件等资源。
    • 本地仓库保管你索引提交的记录,其中HEAD指向最后一次(最新)commit的引用。
    • 索引区类似缓存区域,临时保存改动的内容。
    • 隐藏区主要用于当你需要切换到另一个分支是,暂时保存目前的工作状态(可能有修改没有提交或完成),隐藏目前修改内容等。
Git 小记_第1张图片
git本地仓库[来源git pro]

其中.git目录中的内容

  • objects目录:存储hash记录,第一层目录是sha1哈希的前两位;第二层目录是sha1哈希的后38位,里面的文件已经压缩
  • config文件:项目的配置文件,优先级高于用户目录.gitconfig
  • refs目录:heads中是分支名, tags中是标签名, 文件中是hash编码
    -HEAD文件: 包含当前分支的引用

安装和配置

安装git

Git的官网是https://git-scm.com,可以下载对应系统的git软件。

  • Linux中安装
# fedora/centos, 使用yum或dnf
sudo yum install git
# debian/ubuntu, 使用apt或apt-get
sudo apt-get install git
  • Windows安装,下载地址

    • https://git-scm.com/download/win
    • 此外还有git for windows的项目(http://msysgit.github.io/, https://gitforwindows.org/)
  • macOS: http://git-scm.com/download/mac

此外也可以直接使用GitHub Desktop(适合Windows和Mac),Linux有非官方版本。另外,图形界面的管理软件参见,推荐有 SourceTree。

基础配置

  • 配置本地git用户(全局)
$ git config --global user.name "yourname"
$ git config --global user.email "yourname@email"

说明:必须配置用户名和邮箱信息后才能提交改动信息,--global表示全局(保存在用户路径/.gitconfig文件中),否则用户名和邮箱只在当前仓库有效(保存在项目仓库的。.git/config)。

  • 设置行尾首选项
  • 配置别名,便于使用
$ git config --global alias. 
  • 配置编辑器(默认是vim)
$ git config --global core.editor  
  • 查看所有配置信息
$ git config --list
  • 修改配置文件.gitconfig:
$ git config --global --edit

说明:配置文件包括:

  • /.git/config 仓库级别(优先级最高)
  • /.gitconfig 用户级别(优先级次之),设置时添加参数--global
  • /etc/gitconfig 系统级别(优先级最低),设置时添加参数--system

远程仓库协作

  • 配置SSH密钥(可以避免在上传或拉取代码时输入密码;使用少数可信小团体;权限设置有限)
#  1. 生成SSH Key
$ ssh-keygen -t rsa -C "yourname@email" # 简单的话默认回车

#  2. 将密钥添加到远程服务器端, rsnyc或scp或ssh-copy-id 三选一()
$ rsync -av ~/.ssh/id_rsa.pub username@remote:~/.ssh/authorized_keys
$ scp ~/.ssh/id_rsa.pub username@remote:~/.ssh/authorized_keys
$ ssh-copy-id -i ~/.ssh/id_rsa.pub username@remotet

说明:生成的SSH Key在用户目录下的.ssh目录中,包括id_rsa(私钥文件,绝对不能泄露),id_rsa.pub(公钥文件)

  • 建立本地git仓库,并上传
$ cd local-project
$ git init 
$ git add .
$ git commit -m "initial commit"
$ git remote add origin ssh://username@remote-ip/absolute-path/myrepo.git
$ git push origin master # 上传代码
$ git pull origin master # 拉取代码(更新本地)
  • ssh:// 表示使用ssh协议连接并传输(常用的还有https和git协议)
  • username是服务器仓库所在的用户,如git-name
  • remote-ip局域网中服务器的IP地址,如192.168.0.111
  • absolute-path是仓库所在绝对路径,如/home/git/;也可以使用~等方式表示用户主目录
  • myrepo.git是服务器中所建立的仓库名
  • 获取远程项目并协作
$ git clone [git-repo url] local-reponame
$ ... 操作修改并提交更新
$ git push origin master

local-reponame 是本地仓库的名字,可以为空(目录会自动生成不需要建立,默认为远程仓库名mygrepo,自动忽略.git后缀)


Git基础操作

获得git仓库

一种方式是现有项目初始化

$ git init # 将当前目录转为仓库
$ git init  # 目录可以不存在
$ git init --bare repo-name.git # 建立一个裸的仓库

说明:
git init建立一个新的git仓库,在目录中会有一个.git的目录(隐藏状态)。它可以建立一个空的新仓库或将当前已存在的项目转成git仓库用于版本控制。
--bare裸仓库的作用:
裸仓库中没有工作区,不作为开发环境,一般用于服务器中,且不存放实际文件资源,通常以git作为后缀。

或者,克隆现有仓库,其中仓库地址URL可以使http协议的、git协议、ssh协议等或者本地文件系统路径

# 基本形式是git clone [url]
$ git clone /path/repo-name # 克隆本地仓库,并使用默认名字
$ git clone   # 克隆仓库并使用指定目录名字(会建立一个目录)
$ git clone username@host:/path/repo-name # 远程使用SSH
$ git clone https://path/repo-name # HTTPS协议
$ git clone git:/path/repo-name # git协议

注:克隆仓库是,如果远程仓库是.git作为后缀,会忽略,只有前面一部分作为仓库名。

提交更新

仓库中文件状态通常有:

  • Untracked files:
  • Changes not staged for commit:
  • Changes to be committed:
  • Unmerged paths:
Git 小记_第2张图片
文件状态(来自git pro)



git status查看文件状态,主要指工作区中未缓存的文件和索引区未提交的文件,包括修改的、新添加的、删除的

$ git status

**git add **将工作区文件添加的索引区,同时进行跟踪文件:(提交前的多次索引区域修改会合并)

$ git add  # 添加某个文件
$ git add * # 所有文件
$ git add . # 当前目录所有文件

git rm移除文件

# 移除/删除文件,并从暂存区移除相关追踪
$ git rm  

 # 普通的删除,显示状态为`Changes not staged`
$ rm 

git mv移动文件或改名

$ git mv README.txt README
# 等价于以下三条命令
$ mv README.txt README
$ git rm README.txt
$ git add README

git commit将改动信息提交到仓库

$ git commit -m "message" # 提交信息一般而言是必须的
$ git commit --amend # 合并到上一次提交(会替换为新快照)或修改上一次提交的信息(索引区区没有内容缓存)
$ git commit # 进入编辑页面,输入相关信息保存后会提交
$ git commit -a -m "message" # 直接暂存(-a包括了git add步骤)并提交

如果仅使用git commit会显示一个输入提交信息,可以输入多行说明信息,适合较大的改动。一般格式:第一行是总结性说明(一般50字符以内),空一行,就下来是具体更改的说明(很多开发者采用一般现在时态)
$ git commit提交的是索引区的缓存的快照,对于工作区的内容不干预

git diff查看文件修改

$ git diff --cached
$ git diff --staged # 1.6.1版本以上

git log历史/日志
查看仓库中已提交的历史记录(可以使用以下图形化的工具如gitk)。记录较多时,仅显示最新的记录,空格或回车或箭头等翻页,Q键退出。常见的参数有:

$ git log -n  # 仅显示最新的个
$ git log --oneline # 显示一行的简略信息
$ git log --stat # 额外显示提交增删改变
$ git log -p # 额外显示每次提交的文件差异
$ git log --grep="" # 筛选特定信息的提交
$ git log --graph --oneline # 图形化显示且一行
$ git log --pretty=oneline

注意:git log显示信息说明
第一行 commit后的40个字符是提交信息的SHA-1的校验和,用于保证提交的正确性,作为提交的唯一标识(ID)
第二行是提交人的用户名和邮箱
第三行是提交日期
空一行之后是提交时填写的说明信息。

撤销管理或修改

撤销修改

  • 暂存前,仅本地修改:git checkout filename
  • 已经暂存(git add): git reset HEAD filename;
    其中:reset 命令重置 HEAD 中暂存区的内容。这将清除我们已经暂存 的更改。
  • 已经提交:git revert HEAD (--no-edit) 会进入一个信息编辑页面
    Revert 撤销当前修改,回到HEAD版本(通常是上一个),但实际的提交记录仍然存在

移除提交,使用git reset重置, git log查看会看到撤销的提交,
git reset --hard [tag-name/branch-name/hash-code]
说明:提交信息实际仍然存在,除非使用hash-code进行引用(可从.git目录查看相关记录);另一种方式是预先使用tag做标记,这时使用git log --all仍可以发现那些撤销的提交,标签删除后,相关提交记录也会看不到

修正提交: git commit --amend -m ""

忽略文件

对某些不需要加入git管理,如程序中编译中的中间文件等,建立.gitignore文件进行设定。通常可使用通配符表示需要忽略的文件或目录。

来自git pro的例子

# 此为注释 – 将被 Git 忽略
# 忽略所有 .a 结尾的文件
*.a
# 但 lib.a 除外
!lib.a
# 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
/TODO
# 忽略 build/ 目录下的所有文件
build/
# 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录下所有扩展名为 txt 的文件
doc/**/*.txt

远程同步

git remote管理远程仓库
git remote用于添加、查看和移除你当前仓库与其他仓库的连接,常用一个别名(如origin)代替远程仓库的URL。
Git版本管理中每个本地仓库是相互隔离的,信息是不共享,需要手动将上游仓库拉取(pull)到本地,手动将本地提交推送(push)到远程/中央仓库。

查看
$ git remote # 查看所连接的远程仓库
$ git remote -v # 和上个命令相同,同时显示连接的URL(v==verbose)

# 添加远程仓库(URL表示)的,之后可使用表示远程仓库
$ git remote add   

# 移除
$ git remote remove 

# 重命名
$ git remote rename  

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

讨论:

  1. origin远程连接:使用git clone时默认会建立名为origin的远程连接,方便与远程仓库交互。
  2. 仓库URL: HTTP(HTTPS)是允许匿名但只读,SSH、GIT需要读写。
    另:大多数基于 Git 的项目将它们的中央仓库取名为 origin。

git fetch 获取更新

$ git fetch  # 获取远程仓库所有分支
$ git fetch   # 仅获取特定分支

git pull推送更新到远程仓库

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

git merge合并分支
合并

$ git merge 

解决冲突:
Automatic merge failed; fix conflicts and then commit the result.
冲突文件中的结构:分成两部分;选择合适内容进行保留,通过一次提交就完成合并了

<<<<<<< HEAD
你的修改
=======
master中的修改
>>>>>>> master

分支和标签

git tag管理标签
Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated, 使用-a参数)。区别在于轻量级的标签指向特定提交对象的引用(不变),附注型的则是独立对象,可以使用GPG校验。

$ git tag 查看所有标签
$ git tag -l 'v1.4.2.*' # 使用正则匹配某些标签
$ git tag v1 添加标签
$ git tag -a v1.4 -m 'my version 1.4' # 附注标签,-m标签说明信息
$ git tag -d v1 删除标签

更多

$ git checkout v1^(表示v1的父提交,或使用v1~1)
$ git push origin v1.5 # 通常git push不会将标签传送到远程,除非说明
$ git push origin --tags # 推送所有标签



git branch管理分支,分支代表的是独立的开发流水线。

# 列出所有分支,等于git branch --list
$ git branch 

# 新建一个分支
$ git branch  

# 删除指定分支(如果使用-D用于表示强制删除,包含未合并的更改)
$ git branch -d  

# 重命名当前分支名(-m == --move)
$ git branch -m  

# 切换到已存在分支上
$ git checkout 

# 新建一个分支并切换到新的分支上(如果分支名已存在会报错)
$ git checkout -b  
# 以为基新建分支并切换
$ $ git checkout -b   

git checkout检出、切换分支/标签/提交等

 # 分支切换,如git checkout master 
$ git checkout 

# commit-id(hash-code)指提交历史中显示40位校验和(通常只需要前7位,可以git log --oneline快速查看)
$ git checkout  

# 检出文件(单个或部分文件状态回到过去提交的某一个时刻)
$ git checkout   #检出文件

> 这是的工作区的文件状态与时一直;所有的一切不会影响到当前状态。

注意:这里会修改到你的文件内容,变成旧的内容;如果想舍弃旧的回到当前新的内容: git checkout HEAD

常见问题

error: Your local changes to the following files would be overwritten by checkout:
…
Please commit your changes or stash them before you switch branches.
Aborting

需要先提交/清楚当前仓库中修改的内容

其他命令

  • git revert
  • git reset
  • git rebase
  • git reflog
  • ...

git服务器和分布式协同

参考Linux中搭建GitLab社区版

其他:
简单的git服务器
git daemon --verbose --export-all --base-path=.
--enable=receive-pack 允许推送(git daemon没有权限管理)


参考资料

  • git简明指南(中文):https://rogerdudler.github.io/git-guide/index.zh.html
  • 沉浸式学git(git immersion):里面涉及到一些ruby程序,但不影响
    • [中文翻译( 2014)]http://igit.linuxtoy.org/), Github仓库
    • 英文版, 程序和教程HTML下载(zip文件)
  • GIT 命令“从初学到专业”完整进阶指南[中文翻译] 2017-12-28
  • git教程(阮一峰)
  • git-recipes(git中文教程)
  • git pro 第二版 中文

其他一些详细的资源列表/收藏

  • https://www.jianshu.com/p/25647b9920b7
  • https://github.com/dictcp/awesome-git
  • https://github.com/hylerrix/awesome-git

你可能感兴趣的:(Git 小记)