git使用

好像很久之前使用过git,但是不怎么常用,所以也快忘光了,这次决定写写笔记。还有就是将自己写的脚本用git管理,并托管到github上去。相信就会用的比较熟了。

git作用

  • git是咱linux的创始人linus写出来的一个版本控制管理软件。它当然主要作用就是帮助我们管理文件了,优点就是无论修改了啥它都会有一个记录,而且我们可以回退到修改之前,并不需要备份操作。当然了它还可以多人协作,不过这功能估计一时半会我也用不上。

  • 还有一点就是git就是一个运行在本地的软件而已,并不需要联网,它就可以帮我们管理文件了,初始化后会在目录下创建一个.git的目录,是它用来进行版本控制的。不要把它和github搞混了。

  • 它与github的关系就是,我们可以通过配置,将本地的文件push到github上面去,相当于云端备份了,当然了传到github上面去后,就可以给别人看了。别人pull后就和我们拥有的一模一样,这就是所谓的多人协作。


git使用

git的使用除了pull与push到github上之外,大多数命令都是用来在本地操作的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
git init					#初始化
git status #查看状态
git checkout #撤销修改
git add #添加到暂存区
git restore #从暂存区撤销到修改状态
git checkout #撤销修改
git commit #添加修改到分支
git log #查看修改log
git reflog #查看所有log
git reset #版本回退

git branch #查看分支
git branch branchname #创建分支
git checkout branchname #进入分支
git checkout -b branchname #创建分支并进入分支
git merge branchname #合并分支
git branch -d branchname #删除分支

git tag #显示标签
git tag tagname #创建标签
git tag -d ragname #删除标签

初始化

1
git init

在一个想要使用git来进行版本控制的目录下运行这个命令就可以了。它会在目录下生成一个.git的目录,里面的文件我们一般都不需要改,因为那是它记录我们的所有操作的。这个目录既可以是新建的,也可以是已经有文件的,都没有关系了。

添加name和email

其实不添加也行,添加了在多人协作时,可以找到你嘛

1
2
git config --global user.name 'somename'
git config --global user.email 'xxxxx@qq.com'

加入git管理

前面已经初始化git了,接下来就是告诉git那些东西是要交给它管理的。

  • 这个是使用的最多的一个命令了,用来查看现在的状态

    1
    git status
  • 然后交给git管理

    可以加入目录,文件等

    1
    git add 文件/目录

    也可以将所有东西一次加入

    1
    2
    3
    git add *	
    # or
    git add .
  • 凡是新增文件之后都需要将文件add给git repository,否则git的状态就是一个叉叉,看着不舒服。

提交修改

当我们对文件或者目录做出了修改之后,就需要对修改进行一次提交

  • 可以查看一下状态

    1
    git status
  • 看到有对文件的修改,如果我们想看看具体修改了那些东西可以使用diff

    1
    git diff
  • 进行提交,对子目录的修改等都视为git repository操作,所有随便哪里都可以提交

    • 可以添加指定的文件

      1
      2
      3
      touch 1.txt
      git add 1.txt
      git commit 1.txt -m 'add a new file'

      -m对这次提交的一个说明,如果不写的话,他也会打开一个vi编辑器让你输入。当然了,我的电脑上没有安装vi,所以还是写-m比较简单。否则它也打不开啊

    • 提交所有

      1
      2
      3
      git commit * -m 'add a new file'
      # or
      git commit . -m 'add a new file'

指定忽略文件

由于我们每次修改了之后都是使用星号,不会去指定那个文件,然后进行提交。所以如果有不想提交的目录或者文件怎么办,当然是可以的。我们可以告诉git,那些文件或者目录你不要去管。

1
touch .gitignore

然后将要忽略的目录或者文件名写到里面就行

1
2
3
4
vim .gitignore
1.txt
2.txt
Music

版本回退与恢复

既然是版本控制,那么回退就是它的主要功能了

  • 查看历史版本

    1
    git log
  • 上面是包含了详细信息,如果只看简单的信息

    1
    git log --pretty=oneline
  • 回退到上一个版本使用HEAD^,上上个HEAD^^,回退10个版本HEAD~5

    1
    git reset --hard HEAD^
  • 这样找到回退的几个版本还行,但是如果需要回退的版本比较多,当然就不可能一个一个去数了,git reflog可以查看版本数字,以及唯一索引

    1
    git reflog
  • 比如要回退到某一版本以前,可以找到对应的数字标示,比如HEAD@{20}

    1
    2
    3
    git reset --hard HEAD@{20}
    # 或者使用这个唯一索引,比如为
    git reset --hard 4761129

如果回退之后又想恢复怎么办,只要指定唯一的标识符,就可以恢复。

  • 查看log

    1
    git reflog
  • 随便那个版本,只要指定唯一标示,都可恢复

    1
    2
    3
    4
    #同上,上面已经写过了
    git reset --hard HEAD@{20}
    # 或者使用这个唯一索引,比如为
    git reset --hard 4761129

正确添加以及恢复

  • 修改了文件还未添加到暂存区

    • git checkout将修改的恢复
  • git add将修改后的文件添加到了暂存区stage

    • git restore从暂存区取回
  • git commit将暂存区文件添加到分支master

    • git reset版本恢复

注意点:如果修改了文件,并没有add到暂存区,直接commit后,就会直接添加到分支了,所以只能用git reset来版本回退了

连接github

生成连接的ssh密匙

1
ssh-keygen

然后将 id_rsa.pub中的内容复制到github的密匙中

与github连接:

  • create a new repository on the command line

    本地先新建git仓库

    1
    2
    3
    4
    5
    6
    echo "# dailyScript" >> README.md
    git init
    git add README.md
    git commit -m "first commit"
    git remote add origin https://github.com/ulomo/dailyScript.git
    git push -u origin master
  • push an existing repository from the command line

    本地已近有git仓库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    git remote add origin https://github.com/ulomo/dailyScript.git
    git push -u origin master
    #输入github的用户名和密码就可以成功推送了
    Username for 'https://github.com': ulomo
    Password for 'https://ulomo@github.com':
    Enumerating objects: 79, done.
    Counting objects: 100% (79/79), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (71/71), done.
    Writing objects: 100% (79/79), 10.26 KiB | 700.00 KiB/s, done.
    Total 79 (delta 24), reused 0 (delta 0)
    remote: Resolving deltas: 100% (24/24), done.
    To https://github.com/ulomo/dailyScript.git
    * [new branch] master -> master
    Branch 'master' set up to track remote branch 'master' from 'origin'.

从github克隆已近存在的仓库

1
git clone

创建分支

  • 新建

    1
    2
    3
    git branch 分支名字
    # or
    git checkout -b 分支名字
  • 切换

    1
    git checkout 分支名字
  • 查看分支

    1
    git branch
  • 合并分支

    这种合并不会形成一个commit,(fast forward模式)所以如果删掉分支之后,分支是不可修复的

    1
    git merge 分支名字

    这种就会形成一个commit,即使把分支删了,仍然可以回退分支

    1
    git merge --no-ff -m 'merge branch'
  • 删除分支

    1
    git branch -d 分支名字

分支使用原则及解决冲突

  • 创建的master分支用来merge其他分支

  • 主要工作都在其它创建的分支上,如果也修改了master,提交的时候就会出现矛盾,太麻烦了也。

  • 只有一个master分支和另外一个副分支的话,副分支修改,主分支merge,相安无事。

  • 如果有多个分支,那么就会涉及冲突问题。

    • 首先需要明白merge到底做了些啥:

      1. 如果只有一个分支,可以理解为HEAD指针位置发生了变化

      2. 如果存在多分支,可以理解为master需要融合你想要提交给master的东西的(自己分支可以不包含全部master分支,master分支也不一定就包含全部自己的部分),所有相同的不同的在就全部包含这次子分支提交的信息中,至于说提交过后master又融合了其它分支信息造成的与自己分支信息不同,这就不是master该管的了,因为自己的commit已经提交,也与master融合。

    • 遇到冲突怎么解决:

      冲突是什么造成的,就是内容不同造成的,那么融合做了什么,无非就是合并信息,那么只要把不同的地方修改成相同的。这些不同的信息,会有提示,按照提示进行修改就行。修改完后,再提交修改,这就等于进行了融合。

      1
      2
      git add .
      git commit -m 'merge branch add/change some information'

将当前分支临时存储起来

如果分支内容没有完成,还不能提交。而我们又需要到别的分支去,那我们就要将当前状态存储起来

1
git stash

查看存储的stash

1
git stash list

重新读取存储的内容

1
2
3
git stash apply stash@{数字}
# 然后手动删除存储的状态
git stash drop

下面这种方式就可以取出内容的同时,删掉stash状态,因为用了pop

1
git stash pop

远程多人协作的push与pull

查看远程信息

1
git remote -v

推送到远程

1
2
3
git push origion master
#也可以推送其它分支,比如创建了一个test的分支
git push origion test

远程克隆到本地

1
git clone 地址

这样克隆下来的,只能看到master分支信息。

使用远程的非master分支,比如test分支:

1
git checkout -b test origin/test

这样修改之后push也是无法成功的,因为可能别人以及提交过了。

所以先将最新的版本pull下来,直接pull也是会报错的,需要指定使用的分支

1
git branch --set-upstream test origin/test

再pull下来

1
git pull

然后在本地将master分支与test分支的冲突解决掉,才能push成功。

标签

为什么需要标签呢?有commit不就行了吗?也不是说不行,但是想想我们是不是经常会对分支进行提交,对master进行合并,这样的话,commit信息就比较多了。而标签就是在某个特定时候对整个版本库的一个标记。比如版本发布使用的v1.0,v2.0。但是如果标签打的和commit一样多的话,也就没有意义了。

  • 进入要打标签的分支,一般是master

    1
    git checkout master
  • 打标签

    1
    git tag [-a] 标签 [-m] 说明		#-a指定标签名
    1
    git tag [-s] 标签 [-m] 说明		#-s用私匙签名标签

    eg:

    1
    2
    git tag -a v1.0 -m '版本1'
    git tag -s v1.0 -m '版本1'
  • 查看标签

    1
    git tag
    1
    git show v1.0
  • 对之前的某个commit打标签

    • 查看commit编号

      1
      git log
    • 打标签

      1
      git tag -a v1.0 编号 -m '版本1'
  • 删除标签

    1
    2
    3
    git tag -d 标签名
    eg:
    git tag -d v1.0
  • push标签到远程

    1
    2
    3
    4
    5
    6
    #推送所有标签
    git push origin --tags
    #推送特定标签
    git push origin 标签名
    eg:
    git push origin v1.0
  • 删除远程标签

    • 先删除本地标签

      1
      git tag -d v1.0
    • 在同步远程进行删除

      1
      2
      3
      git push origin :refs/tags/标签名
      eg:
      git push origin :refs/tags/v1.0

命令设置别名

如果觉得命令太难记,还可以设置别名。例如将commit设置为cm

1
git config --global alias.cm commit

搭建自己的git服务器

  1. 在服务器上安装git

    1
    sudo apt-get install git
  2. 加入git用户,目的是权限管理

    1
    sudo useradd git -m /home/git
  3. 导入允许连接的ssh key认证密匙

    1
    2
    ssh-keygen
    touch ~/.ssh/authorized_keys

    将需要连接git仓库的电脑的~/.ssh/id_rsa.pub中的信息放入上面创建的文件中

  4. 创建git仓库目录

    1
    2
    3
    4
    5
    # 随便创建个目录
    mkdir ~/git_repository
    cd ~/git_repository
    # 给仓库取个名字
    git init --bare somename.git
  5. 将权限全部给到git

    1
    sudo chown -R git:git somename.git
  6. 禁止shell登录git,为了安全

    1
    2
    3
    4
    sudo vim /etc/passwd
    # 修改shell为git-shell
    eg:
    git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
  7. 克隆仓库到自己电脑

    1
    git clone git@server:/home/git/git_repository/somename.git