Git基础教程

说明

  • 阅读此博文之前,请先阅读本人有关CSDN博客的 相关说明
  • 本文的 git教程 基于 Ubuntu 18.04 64位,所有命令均由本人亲手敲过验证。Windows下未进行实操,请有需要者自行尝试
  • 本文的 git教程 属于新手教程,但满足日常工作的基本需要。git的进阶请需要时自行查找相关资料
  • 本文可能较长,但知识点分类较明确,若当作手册使用,请点击右侧工具栏的目录选项
  • 部分重要说明是以 注释 形式呈现,请勿忽视!

集中式

  • 集中式版本控制系统,版本库集中存放在中央服务器,工作之前要先从中央服务器取得最新的版本,然后开始工作,工作结束,再把更新后的版本推送给中央服务器
  • 集中式版本控制系统最大的缺点就是必须联网才能工作
  • CVS、SVN、ClearCase

分布式

  • 分布式版本控制系统没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,工作的时候,就不需要联网。对于多人协作,只需把各自的修改推送给对方,就可以互相看到对方的修改了
  • 和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法工作
  • 在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能双方不在一个局域网内,两台电脑互相访问不了,也可能其他人电脑没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也可以正常工作,只是交换修改不方便而已
  • git、BitKeeper、Mercurial、Bazaar

安装

  • 终端输入 git 会有提示安装的命令
  • 配置
    git config --global user.name "Your Name"
    git config --global user.email "email@example.com"
    
    注:git config命令的--global参数,表示这台机器上所有的Git仓库都会使用这个配置,也可以对某个仓库指定不同的用户名和Email地址
    

创建版本库

mkdir xxx
cd xxx
git init
  • 注: Windows系统下,为了避免遇到各种莫名其妙的问题,确保目录名(包括父目录)不包含中文
  • 所有的版本控制系统,只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以显示每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了什么,版本控制系统不知道,也没法知道
  • 不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,如果要真正使用版本控制系统,就要以纯文本方式编写文件。因为文本是有编码的,比如中文有常用的GBK编码,日文有Shift_JIS编码,如果没有历史遗留问题,强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持
  • 使用Windows要特别注意: 千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队在每个文件开头添加了0xefbbbf(十六进制)的字符,可能会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误等等,都是由记事本的行为带来的。可以使用Notepad++ 代替记事本(把Notepad++的默认编码设置为UTF-8 without BOM)

删除本地版本库

  • 删除版本库中的 .git 目录
  • 删除整个版本库目录

添加文件

vi README
git add README
git commit -m "wrote a README file"

注:commit可以一次提交很多文件,所以可以多次add不同的文件

改动文件并提交

(1)
vi README
git diff <file>   # 查看不同
git add README 
git commit -m "modify README"
(2)
vi README
git commit -am "modify README"

注:git commit -am "message" = git add . + git commit -m "message"

(3) 提交多行注释
git commit -m '1. xxx
>2. xxx'

(4) 修改最后一次commit描述
// 修改方式同vi的使用
git commit --amend

(5) 修改指定commit描述
git rebase -i HEAD~n
然后将 pick 修改为 r或edit
git commit --amend
git rebase --continue

合并多个commit

  • 假设有如下提交记录
    * b1b8189 - (HEAD -> master) Commit-3
    * 5756e15 - Commit-2
    * e7ba81d - Commit-1
    * 5d39ff2 - Commit-0
    
  • 假设需求是合并commit-3和commit-2
    git rebase -i e7ba81d   # 不包含指定的e7ba81d 
    
    pick e7ba81d Commit-2
    pick 5756e15 Commit-3
    # Rebase e7ba81d..b1b8189 onto e7ba81d (2 command(s))
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    # e, edit <commit> = use commit, but stop for amending
    # s, squash <commit> = use commit, but meld into previous commit
    # f, fixup <commit> = like "squash", but discard this commit's log message
    # x, exec <command> = run command (the rest of the line) using shell
    # b, break = stop here (continue rebase later with 'git rebase --continue')
    # d, drop <commit> = remove commit
    # l, label <label> = label current HEAD with a name
    # t, reset <label> = reset HEAD to a label
    # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
    # .       create a merge commit using the original merge commit's
    # .       message (or the oneline, if no original merge commit was
    # .       specified). Use -c <commit> to reword the commit message.
    
  • 将 5756e15 前的 pick 修改为 squash 或 s,表示与前一个commit进行合并,即e7ba81d,退出前会让你决定commit message,最后仓库是commit-3的状态
  • 或将 5756e15 前的 pick 修改为 fixup 或 f,表示与前一个commit进行合并,即e7ba81d,但会直接使用commit-2 的commit message,最后仓库是commit-3的状态
  • 注:使用drop的话会删除提交的内容,慎用

版本回退

git log [--pretty=oneline]

481f602ef4693fe40f393447014e95ee8e535a72 (HEAD -> master) add try
22929efaca9b2f12bad10420f4c1e41ba043c2e8 add distributed
7c5124871bb5a58afe2c3826ecc0a492be85a1e6 wrote a README file

# 前面一大串类似481f602...的是commit id(版本号)
# 和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示
# 每个人看到的commit id肯定不一样,以自己的为准
# Git是分布式的版本控制系统,当多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,会产生冲突
  • 在Git中,用HEAD表示当前版本,也就是最新的提交481f602…,上一个版本就是 HEAD^,上上一个版本就是 HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成 HEAD~100
# 回退到上一个版本
git reset --hard HEAD^
# 回到指定的未来版本(版本号没必要写全)
git reset --hard 481f602
# 记录每一次命令
# 可用于找回 commit id
git reflog

暂存当前工作内容

git stash	# 不会暂存untracked files
# 推荐使用
git stash save -a "temporary save"
git stash pop	# 将缓存堆栈中的第一个stash删除,并将对应修改应用到当前的工作目录下
git stash apply	# 将缓存堆栈中的stash多次应用到工作目录中,但并不删除stash拷贝
git stash list	# 查看现有stash
git stash drop stash@{0}	# 移除stash

工作区和暂存区

  • 工作区:在电脑里能看到的目录
  • 版本库:工作区的隐藏目录 .git
    • Git的版本库里存了很多东西,其中最重要的就是称为 stage(或者叫 index)的暂存区,还有Git为我们自动创建的第一个分支 master,以及指向 master 的一个指针叫 HEAD
    • 把文件往Git版本库里添加的时候,是分两步执行的
      • 第一步是用 git add 把文件添加进去,实际上就是把文件修改添加到暂存区
      • 第二步是用 git commit 提交更改,实际上就是把暂存区的所有内容提交到当前分支
  • 注: 每次修改,如果不用 git add 到暂存区,那就不会加入到 commit

状态查询

  • 显示工作目录和暂存区的状态
    $ git status
    
  • 仓库很大,管理文件较多时使用以下命令可能可以加快速度
    $ git status -uno
    

撤销修改

  • 当修改了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令 git checkout -- <file>
  • 当修改了工作区某个文件的内容,且添加到了暂存区时,想丢弃修改,分两步,第一步用命令 git reset HEAD <file>,就回到了上一步,第二步按上一步操作
  • 已经提交了不合适的修改到版本库时,想要撤销本次提交,进行版本回退,不过前提是没有推送到远程库

删除文件

# 从工作区删除文件,可以使用 git checkout -- <file> 恢复
rm text

# 从暂存区删除文件,可以使用 git reset HEAD <file> 恢复
git rm text

# 将暂存区的操作提交到版本库
git commit -m "rm text"

远程仓库

  • 创建SSH Key: 在用户主目录下,查看是否存在 .ssh 目录,如果有,再查看该目录下是存在 id_rsa(私钥)和 id_rsa.pub(公钥)这两个文件,如果有,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key
    ssh-keygen -t rsa -C "youremail@example.com"
    
  • 登陆GitHub,打开【Settings】->【SSH and GPG Keys】页面。然后点【New SSH Key】,填上任意Title,在Key文本框里粘贴 id_rsa.pub 文件的内容

添加远程库

  • 登陆GitHub,创建一个新的仓库
  • 关联本地仓库
    git remote add origin git@github.com:yourLoginName/yourRepository.git
    
  • 把本地库的所有内容推送到远程库上
    git push -u origin master
    
    # 用git push命令,实际上是把当前分支master推送到远程
    # 由于远程库是空的,第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令:git push origin master
    
  • SSH警告: 当第一次使用Git的 clone 或者 push 命令连接GitHub时,会得到一个警告
    The authenticity of host 'github.com (192.23.253.75)' can't be established.
    RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
    Are you sure you want to continue connecting (yes/no)?
    
    • 这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可
    • Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了
      Warning: Permanently added 'github.com,192.23.253.75' (RSA) to the list of known hosts.
      

从远程库克隆

  • 假设从零开发,最好的方式是先创建远程库,然后,从远程库克隆
  • 首先,登陆GitHub,创建一个新的仓库,名字叫 gitskills
  • 克隆一个本地库
    # 地址可以直接在github上复制
    git clone git@github.com:yourLoginName/gitskills.git
    

分支优势

  • 假设准备开发一个新功能,但是需要两周才能完成,第一周写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致其他人不能工作。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险
  • 现在有了分支,就不用怕了。每个人创建一个属于自己的分支,别人看不到,还继续在原来的分支上正常工作,而自己则在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作

创建与合并分支

查看分支:git branch
查看远程分支:git branch -r  # 还有其他命令,需要时查询

创建分支:git branch <name>

切换分支:git checkout <name>

创建+切换分支:git checkout -b <name>

合并某分支到当前分支:git merge <name>

删除分支:git branch -d <name>

合并某分支上特定commit到某/新分支:
(1) git checkout master
    git cherry-pick commit-id
(2) git checkout -b new-branch commit-id

合并某分支上一系列commits到某/新分支
# 假设需要合并feature分支的commit 76cada ~ 62ecb3
(1) git checkout -b newbranch 62ecb3
    git rebase --onto master 76cada^
  • HEAD 严格来说不是指向提交,而是指向 mastermaster 才是指向提交的,所以,HEAD 指向的就是当前分支。
  • 一开始的时候,master 分支是一条线,Git用 master 指向最新的提交,再用 HEAD 指向 master,就能确定当前分支,以及当前分支的提交点。每次提交,master 分支都会向前移动一步
  • 当创建新的分支,例如 dev 时,Git新建了一个指针叫 dev,指向 master 相同的提交,再把 HEAD 指向 dev,就表示当前分支在 dev
  • 从现在开始,对工作区的修改和提交就是针对 dev 分支了,比如新提交一次后,dev 指针往前移动一步,而 master 指针不变
  • 假如在 dev 上的工作完成了,就可以把 dev 合并到 master 上,即直接把 master 指向 dev 的当前提交,就完成了合并
  • 合并完分支后,可以删除 dev 分支。删除 dev 分支就是把 dev 指针给删掉,删掉后,就剩下了一条 master 分支

解决冲突

  • master 分支和其他分支各自都分别有新的提交,则产生冲突
  • 合并时会提醒冲突或使用 git status 查看
  • 修改冲突再提交(只针对master)
  • 查看分支合并情况
    git log --graph --pretty=oneline --abbrev-commit
    

分支管理策略

  • 通常,合并分支时,如果可能,Git会用 Fast forward 模式,但这种模式下,删除分支后,会丢掉分支信息

  • 如果要强制禁用 Fast forward 模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息

    # 本次合并要创建一个新的commit,加上-m参数,写入commit描述
    git merge --no-ff -m "merge with no-ff" dev
    
  • 首先,master 分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面工作

  • 工作都在 dev 分支上,也就是说,dev 分支是不稳定的,到某个时候,比如1.0版本发布时,再把 dev 分支合并到 master 上,在 master 分支发布1.0版本

  • 每个人都在 dev 分支上工作,每个人都有自己的分支,时不时地往 dev 分支上合并即

  • 所以,团队合作的分支看起来就像这样

    团队合作分支图

Bug分支

  • 有其他任务进来,需要创建一个新的分支完任务,但是当前分支上任务还未完成,无法提交
    # "储藏"当前工作现场,等以后恢复现场后继续工作
    git stash
    
    # 查看“储藏”的工作现
    git stash list
    
    # 恢复工作现场,但恢复后,stash内容并不删除
    git stash apply
    # 删除stash中被恢复的工作现场
    git stash drop
    
    # 恢复的同时把stash内容也删了
    git stash pop
    
    # 可以多次stash
    # 恢复的时候,先进行查看stash
    git stash list
    # 恢复指定的stash
    git stash apply stash@{0}
    

Feature分支

  • 添加一个新功能时,肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支
  • 如果要丢弃一个没有被合并过的分支,可以通过 git branch -D <name> 强行删除

多人协作

  • 查看远程库的信息
    git remote
    
    # 显示更详细的信息
    # 假设远程仓库名为 repository
    $ git remote -v
    origin	git@github.com:yourLoginName/repository.git (fetch)
    origin	git@github.com:yourLoginName/repository.git (push)
    
    注:显示可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址
    
  • 推送分支
    # 推送分支,就是把该分支上的所有本地提交推送到远程库
    # 推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上
    $ git push origin master
    
    # 推送其他分支,比如dev
    $ git push origin dev
    
    • 并不是一定要把本地分支往远程推送
    • master分支是主分支,因此要时刻与远程同步
    • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步
    • bug分支只用于在本地修复bug,就没必要推到远程
    • feature分支是否推到远程,取决于你是否和你的团队合作在上面开发
  • 抓取分支
    • 当其他人从远程库 clone 时,默认情况下,他只能看到本地的 master 分支
    • 要在dev分支上开发,就必须创建远程 origindev 分支到本地
      # 本地和远程分支的名称最好一致
      git checkout -b dev origin/dev
      
  • 更新远程分支列表
    git remote update origin --prune
    
  • 解决冲突
    • 指定本地 dev 分支与远程 origin/dev 分支的链接
      git branch --set-upstream-to=origin/dev dev
      
    • 把最新的提交从 origin/dev 抓下来
      git pull
      
    • 本地合并,解决冲突,推送

与远程同步

  • 这一部分是后来补充进来的,主要是实际遇到了两个场景,可以利用以下方法解决,可能在此过程中会需要一些比较操作,故都整合在了这里,而没有放入相对应的小节
    • 向更新频繁的开源项目贡献代码的时候,经常会遇到远程代码比自己本地要超前几个版本。这时候就需要先进行同步
    • 之前有同事一直使用 svn,刚刚转战 git,抱怨 git 不能查看远程仓库的变化,其实还是对 git 不熟悉啦
  • 抓取远程分支
    # master 想要抓取的远程某分支
    # latest 本地电脑上的分支,如果不存在会自动创建
    $ git fetch git@github.com:loginName/project.git master:latest
    
    注:git pull 等同于先利用 git fetch 获得当前指向的远程分支,然后利用 git merge 将其与本地的当前分支合并
    
  • 分支比较
    • 查看 dev 有,master 中没有的
      $ git log dev ^master
      
    • 查看 master 中有,dev 中没有的
      $ git log master ^dev
      
    • 查看 dev 中比 master 多提交的内容
      # 结果为两个点后的分支比两个点前的分支多提交的内容
      $ git log master..dev
      
      # 同理
      $ git log dev..master
      
    • 纯粹比较两分支间的不同
      $ git log master...dev
      
    • 显示出每个提交是在哪个分支上
      # 注意 commit 后面的箭头,根据在 –left-right dev…master 的顺序,左箭头 < 表示是 dev 的,右箭头 > 表示是 master的
      $ git log --left-right dev...master
      
  • 分支间文件比较
    # 显示出所有有差异的文件列表以及内容增删行数情况
    $ git diff branch1 branch2 --stat
    
    # 显示分支间指定文件的详细差异
    $ git diff branch1 branch2 <filename>
    
    # 显示出所有有差异的文件的详细差异
    $ git diff branch1 branch2
    
  • 图形化操作
    • Windows 下使用 git 提供的 gui 工具 gitk,可以清晰地查看搜索提交历史及 git 相关操作。在终端 git 仓库目录下输入 gitk 命令即可使用

标签管理

  • 发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照
  • Git的标签虽然是版本库的快照,但其实它就是指向某个 commit 的指针(分支可以移动,标签不能移动
  • tag 就是一个让人容易记住的有意义的名字,它跟某个 commit 绑在一起
  • 创建标签
    • 切换到需要打标签的分支上
      # 打一个新标签
      $ git tag <name>
      
      注:默认标签是打在最新提交的commit上的
      
      # 针对特定提交打标签
      $ git tag <tag_name> <commit_id>
      
      # 创建带有说明的标签,用-a指定标签名,-m指定说明文字
      $ git tag -a <tag_name> -m "message" <commit_id>
      
  • 查看所有标签
    $ git tag
    
    注:标签不是按时间顺序列出,而是按字母排序
    
  • 查看标签信息
    $ git show <tagname>
    
  • 删除标签
    $ git tag -d <tag_name>
    
    注:创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除
    
  • 推送某个标签到远程
    $ git push origin <tagname>
    
  • 一次性推送全部尚未推送到远程的本地标签
    $ git push origin --tags
    
  • 删除远程标签
    # 先从本地删除
    $ git tag -d <tag_name>
    
    # 然后,从远程删除
    $ git push origin :refs/tags/<tagname>
    

Patch

  • 生成 patch
    # -M 表示从 commit_id 开始,向下的 M 次提交(包含此次),计数从1开始
    # commit_id 写前几位即可
    $ git format-patch commit_id -M 
    
  • 检查 patch
    # 若 patch 与需要打 patch 的文件不在同一目录,则需要加上 patch 所在路径名
    $ git apply --check xxx.patch
    
  • 打 patch(无冲突情况)
    # 打 patch 前需检查 patch 是否可用
    # 若 patch 与需要打 patch 的文件不在同一目录,则需要加上 patch 所在路径名
    $ git am *.patch
    

忽略特殊文件

  • 有些时候,必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件等等,每次 git status 都会显示 Untracked files ...
  • 在Git工作区的根目录下创建一个特殊的 .gitignore 文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件
  • 不需要从头写 .gitignore 文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
  • 忽略文件的原则
    • 忽略操作系统自动生成的文件,比如缩略图等;
    • 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如 Java 编译产生的 .class 文件;
    • 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件
    • 假设在Windows下进行Python开发,Windows会自动在有图片的目录下生成隐藏的缩略图文件,如果有自定义目录,目录下就会有 Desktop.ini 文件,因此需要忽略Windows自动生成的垃圾文件
      # Windows:
      Thumbs.db
      ehthumbs.db
      Desktop.ini
      
    • 然后,继续忽略Python编译产生的 .pyc.pyodist 等文件或目录
      # Python:
      *.py[cod]
      *.so
      *.egg
      *.egg-info
      dist
      build
      
    • 加上自己定义的文件,最终得到一个完整的 .gitignore 文件,内容如下
      # Windows:
      Thumbs.db
      ehthumbs.db
      Desktop.ini
      
      # Python:
      *.py[cod]
      *.so
      *.egg
      *.egg-info
      dist
      build
      
      # My configurations:
      db.ini
      deploy_key_rsa
      
    • 最后一步就是把 .gitignore 也提交到Git。检验 .gitignore 的标准是 git status 命令是不是说 working directory clean
    • 使用Windows时注意,如果在资源管理器里新建一个 .gitignore 文件,会提示必须输入文件名,但是在文本编辑器里“保存”或者“另存为”就可以把文件保存为 .gitignore
    • 有些时候,想添加一个文件到Git,但发现添加不了,原因是这个文件被 .gitignore 忽略了,如果确实想添加该文件,可以用 -f 强制添加到Git
      git add -f <filename>
      
    • 可能是 .gitignore 写得有问题,需要找出来到底哪个规则写错了,可以用 git check-ignore 命令检查
      $ git check-ignore -v App.class
      .gitignore:3:*.class    App.class
      
    • .gitignore 文件本身要放到版本库里,并且可以对 .gitignore 做版本管理

自定义git

  • 让Git显示颜色
    git config --global color.ui true
    
  • 配置别名
    • --global 参数是全局参数,也就是以下命令在这台电脑的所有Git仓库下都有用
    • 配置Git的时候,加上 --global 是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用
    # 为 status 设置别名 st
    $ git config --global alias.st status
    
    # co表示checkout,ci表示commit,br表示branch
    $ git config --global alias.co checkout
    $ git config --global alias.ci commit
    $ git config --global alias.br branch
    
    $ git config --global alias.unstage 'reset HEAD'
    
    git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
    
  • 配置文件
    • 每个仓库的Git配置文件都放在 .git/config 文件中
    • 当前用户的Git配置文件放在用户主目录下的一个隐藏文件 .gitconfig
      [user]
      	name = xxx
      	email = xxxxxx@xxx.com
      [color]
      	ui = true
      [alias]
      	lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
      
    • 配置别名可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置

搭建Git服务器

  • 搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装
  • 假设已经有sudo权限的用户账号
  • 第一步,安装git
    $ sudo apt-get install git
    
  • 第二步,创建一个git用户,用来运行git服务
    $ sudo adduser git
    
  • 第三步,创建证书登录
    • 收集所有需要登录的用户的公钥,就是他们自己的 id_rsa.pub 文件,把所有公钥导入到 /home/git/.ssh/authorized_keys 文件里,一行一个
  • 第四步,初始化Git仓库
    • 先选定一个目录作为Git仓库,假定是 /srv/sample.git,在 /srv 目录下输入命令
      $ 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 命令克隆远程仓库了,在各自的电脑上运行
      $ git clone git@server:/srv/sample.git
      Cloning into 'sample'...
      warning: You appear to have cloned an empty repository.
      
  • 管理公钥
    • 如果团队很小,把每个人的公钥收集起来放到服务器的 /home/git/.ssh/authorized_keys 文件里就是可行的。如果团队有几百号人,可以用 Gitosis 来管理公钥
  • 管理权限
    • 有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite 就是这个工具
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值