della0887 发表于 2018-9-18 12:32:08

Git基本概念及操作(2)

  想要深入的了解GIT,还得回到常见版本管理系统中的version概念。前面我们说到一个文件在不同的时间会产生不同的版本,那版本管理系统怎么记录这些不同的版本,是每一个时间保存一个文件,还是保存这些差异点,然后合并呢?这里通常有两种实现方式,一种是保存变更差异,如下图所示:

  这种方式广泛采用在CVS/SVN中,好处是管理系统保存单个版本所用的空间不需要很大。但坏处很明显,比喻说我在版本4处想要拿到File A/B/C的拷贝,需要经过三次比较计算才能拿到准备的版本数据。并且这当中任何一个版本数据丢失了我就不能得到当前版本数据。第二种是每次都保存,只要有变化就保存。如下图所示:

  这种方式就是对每一个版本的每一个文件进行HASH计算,一旦发现HASH不同就诞生一个新的文件,如果相同说明文件没变化。因此,这种管理下每个版本实际是保存单独的文件,与前一个版本不需要进行差异化比较。取出一个新版本的效率大大增强。所获得的好处是非常明显的。GIT就是采用这种方案的。GIT采用SHA-1计算出每种管理对象(Element)的HASH值,通过这些HASH值来组成一个管理对象树。
  前面我们讲的集中式版本管理系统通常都是C/S架构,一个Repository,多个Client。那么对GIT这种分布式版本管理系统,其基本架构怎么样呢?其实也类似,只是说C/S都在本地。GIT对源码的管理分成三块,一块是Repository通常是以.git目录下保存的数据,一块是工作区 working area,是与.git目录同级的其它目录及子目录都是工作区,注意工作区中不一定是所有的文件都是受控的,只有当你的文件加入REPO后才是受控的。第三块就是比较难以理解的暂定区staging area. Staging area实际上是.git目录中一个索引文件,也就是这个文件的HASH值。如下图所示:

  其中Working directory是项目的检出版本,这个检出版本跟你当前的工作分支是相关的。缺省工作分支是master。这个有点类似于CC中VIEW概念。一旦你将当前工作目录中的所有文件都commit后,这些目录中的文件实际上是可以删除的。这一点同CC中VIEW非常相似。Staging area是一个记录暂存区,在GIT目录中表现为索引文件,与正式COMMIT区别就是状态未变。如下图所示:

  了解了上面两大基本概念之后,我们可以结合实际操作来深入了解GIT的一些基本理念,这些理念实际上也就是在GIT下是如何定义版本与分支、TAG、HEAD及其之间的关系。
  【1】GIT配置。GIT目前是没有权限系统的,或者说权限非常弱的。GIT的权限目前主要是靠操作系统,所以GIT配置中是没有权限配置的。GIT配置分成全局配置、用户配置和项目配置。全局配置适用于操作系统的所有用户,用户配置适用于当前用户,项目配置适用于当前项目。每一个级别的配置都会覆盖上层的相同配置。这三种配置区别在于存储目录和使用命令选项不同。
  1)全局配置 /etc/gitconfig(相对于安装路径,有时候没有) 命令git config –system
  2)用户配置 ~/.gitconfig 或者$HOME/.gitconfig git-config –global
  3)项目配置 项目.git目录中config目录下 git config
  # cat /root/.gitconfig
  
  gitproxy = /work/bongos/bin/git-proxy
  
  tool = vimdiff
  # ls -latr /etc/gitconfig
  ls: cannot access /etc/gitconfig: No such file or directory
  # ls -latr ~/.gitconfig
  -rw-r--r--. 1 root root 70 Apr 20 16:01 /root/.gitconfig
  # ls -latr .git/config
  .git/   test.c
  # ls -latr .git/config
  -rw-r--r--. 1 root root 92 Apr 20 15:27 .git/config
  # git config --list
  core.gitproxy=/work/bongos/bin/git-proxy
  merge.tool=vimdiff
  core.repositoryformatversion=0
  core.filemode=true
  core.bare=false
  core.logallrefupdates=true
  # git config --global user.name "ROOT root"
  # git config --global user.emal "root@root.com"
  # cat ~/.gitconfig
  
  gitproxy = /work/bongos/bin/git-proxy
  
  tool = vimdiff
  
  name = ROOT root
  emal = root@root.com
  # git config user.name "PROJ proj"
  # git config user.email "proj@proj.com"
  # cat .git/config
  
  repositoryformatversion = 0
  filemode = true
  bare = false
  logallrefupdates = true
  
  name = PROJ proj
  email = proj@proj.com
  # git config --list
  core.gitproxy=/work/bongos/bin/git-proxy
  merge.tool=vimdiff
  user.name=ROOT root
  user.emal=root@root.com
  core.repositoryformatversion=0
  core.filemode=true
  core.bare=false
  core.logallrefupdates=true
  user.name=PROJ proj
  user.email=proj@proj.com
  # git config user.name
  PROJ proj
  # git config --global user.name
  ROOT root
  #
  GIT配置还有三个其他配置,一个就是命令的自动完成,还有一个命令别名。最后一个就是gitignore .自动完成需要一个BASH,这个文件通常在contrib目录下,需要进行如下图所示的配置:

  别名是使用git config 来定义alias.*
  1008git config --global alias.co checkout
  1009git config --global alias.br branch
  1010git config --global alias.ci commit
  1011git config --global alias.st status
  1012git config --global alias.unstage 'reset HEAD --'
  1013git config --global alias.last 'log -1 HEARD'
  1014git last
  1015git config --global alias.last 'log -l HEAD'
  1016git last
  1017git log -l
  1018git log -1 HEAD
  1019git help log
  1020git log -1 HEAD
  1021git log -l HEAD
  1022history
  # git config --list
  core.gitproxy=/work/bongos/bin/git-proxy
  merge.tool=vimdiff
  user.name=ROOT root
  user.emal=root@root.com
  alias.co=checkout
  alias.br=branch
  alias.ci=commit
  alias.st=status
  alias.unstage=reset HEAD --
  alias.last=log -l HEAD
  core.repositoryformatversion=0
  core.filemode=true
  core.bare=false
  core.logallrefupdates=true
  user.name=PROJ proj
  user.email=proj@proj.com
  #
  对一个项目如果不想将工作目录中一些临时或者编译产生的文件纳入git管理,可以通过创建.gitignore文件来告诉git。

  【2】仓库建立。建立GIT项目仓库,一种是完全新的创建,也就是说让项目所在的目录成为GIT受控,只需要执行命令git init,另一种是别的已有的克隆一个出来,执行git clone 如git clone git://github.com/schacon/grit.git。
  # git init
  Reinitialized existing Git repository in /work/bongos/mygit/.git/
  # git status
  # On branch master
  #
  # Initial commit
  #
  # Changes to be committed:
  #   (use "git rm --cached ..." to unstage)
  #
  #    new file:   test.c
  #
  # ls
  test.c
  # vi README
  # git status
  # On branch master
  #
  # Initial commit
  #
  # Changes to be committed:
  #   (use "git rm --cached ..." to unstage)
  #
  #    new file:   test.c
  #
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    README
  #
  GIT是分布式,GIT在任何一个地方的仓库都保存全部的信息,但绝大部分项目团队为了开发协同的需要,通常建立一个远程仓库来协同相互之间的开发,也就是说大家都与远程仓库进行同步,就实现了相互之间的同步。GIT本地与远程之间支持多种协议,常见git/https等。远程仓库通常以URL形貌提供,但实际上它是一个有命名的。通常默认是origin。对远程仓库如何操作管理,有一些常用的命令,如下:
  1)查看远程库 git remote –v或者git remote show origin
  # git remote -v
  origin    git://git.videolan.org/vlc-ports/android.git (fetch)
  origin    git://git.videolan.org/vlc-ports/android.git (push)
  # git remote
  origin
  # git remote show origin
  * remote origin
  Fetch URL: git://git.videolan.org/vlc-ports/android.git
  PushURL: git://git.videolan.org/vlc-ports/android.git
  HEAD branch: master
  Remote branch:
  master tracked
  Local branch configured for 'git pull':
  master merges with remote master
  Local ref configured for 'git push':
  master pushes to master (local out of date)
  #
  2)添加远程库 git remote add pt git://github.com/paulboone/ticgit.gi
  3)抓取数据git fetch pb这里有两个需要注意的是无端分支与本地分支它不是自动合并的到本地分支的。
  # git fetch origin
  remote: Counting objects: 86, done.
  remote: Compressing objects: 100% (50/50), done.
  remote: Total 60 (delta 40), reused 0 (delta 0)
  Unpacking objects: 100% (60/60), done.
  From git://git.videolan.org/vlc-ports/android
  628d90c..b88d59dmaster   -> origin/master
  # cd vlc
  4)推送数据 git push origin master
  5)删除远程仓库 git remote rename pb paul或者git remote rm paul
  【3】git常用操作 GIT的操作方式与一般的SCM不同,通常的SCM是先检出后工作再受近。GIT是在创建仓库之后就可以对当前文件进行修改,也就是说默认状态下所有文件都是可以修改的。修改后文件用户可以提交仓库GIT进行监管。如下图所示:

  下面将常用的操作命令结合起来示例如下图所示:

  下面演示一些常用的操作,这些操作包括删除文件、重命名文件、撤消提交、撤消跟踪、撤消修改及查看日志:
  1)删除,采用git rm,单独的rm只会将工作区中文件删除,仓库中没有删除,还有可能通过checkout检出来进行恢复。如果使用git rm则会将文件从仓库中删除,不能恢复。
  # git status
  # On branch master
  nothing to commit (working directory clean)
  # ls
  READMEtest.c
  # rm README
  rm: remove regular file `README'? y
  # git status
  # On branch master
  # Changes not staged for commit:
  #   (use "git add/rm ..." to update what will be committed)
  #   (use "git checkout -- ..." to discard changes in working directory)
  #
  #    deleted:    README
  #
  no changes added to commit (use "git add" and/or "git commit -a")
  # git checkout README
  # ls
  READMEtest.c
  # git rm README
  rm 'README'
  # git status
  # On branch master
  # Changes to be committed:
  #   (use "git reset HEAD ..." to unstage)
  #
  #    deleted:    README
  #
  # ls -latr
  total 16
  drwxr-xr-x. 12 root root 4096 Apr 20 15:27 ..
  -rw-r--r--.1 root root   18 Apr 20 15:27 test.c
  drwxr-xr-x.3 root root 4096 Apr 26 16:35 .
  drwxr-xr-x.8 root root 4096 Apr 26 16:35 .git
  # git checkout README
  error: pathspec 'README' did not match any file(s) known to git.
  # git commit -m "delete "
   delete
  1 file changed, 7 deletions(-)
  delete mode 100644 README
  # git statue
  git: 'statue' is not a git command. See 'git --help'.
  Did you mean this?
  status
  # git st
  # On branch master
  nothing to commit (working directory clean)
  #
  2)重命名文件,相当于先删除后加入 git mv
  # vi readme
  # git commit -a -m "new readme commit"
  # On branch master
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    readme
  nothing added to commit but untracked files present (use "git add" to track)
  # git status
  # On branch master
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    readme
  nothing added to commit but untracked files present (use "git add" to track)
  # git commit -a -m "new readme commit"
  # On branch master
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    readme
  nothing added to commit but untracked files present (use "git add" to track)
  # ls
  readmetest.c
  # git add readme
  # git commit -a -m "new readme commit"
   new readme commit
  1 file changed, 1 insertion(+)
  create mode 100644 readme
  # git status
  # On branch master
  nothing to commit (working directory clean)
  # git mv readme README
  # git status
  # On branch master
  # Changes to be committed:
  #   (use "git reset HEAD ..." to unstage)
  #
  #    renamed:    readme -> README
  #
  # git commit -a -m "move file name"
   move file name
  1 file changed, 0 insertions(+), 0 deletions(-)
  rename readme => README (100%)
  # git status
  # On branch master
  nothing to commit (working directory clean)
  3)git log 可以显示操作日志,有多种方式,格式化也行,使用gitk图形化展示也可以。
  # git log
  commit 1868051cb93d4223a27f91b55b15e5b1cc3ab980
  Author: PROJ proj
  Date:   Thu Apr 26 16:44:18 2012 +0800
  move file name
  commit e529597105dded8688536ab5b37118e2597f8956
  Author: PROJ proj
  Date:   Thu Apr 26 16:43:19 2012 +0800
  new readme commit
  commit 24c68710bad22d65319acb3776ea70ca1720df0a
  Author: PROJ proj
  Date:   Thu Apr 26 16:37:43 2012 +0800
  delete
  commit 5399ad857c13085e00af125f04e5d3be2d22febc
  Author: PROJ proj
  Date:   Wed Apr 25 17:31:12 2012 +0800
  the forth commit
  commit 5cb0791c037545f3167c6af179a13dbdd5f395fe
  Author: PROJ proj
  Date:   Wed Apr 25 17:30:07 2012 +0800
  third commit
  commit 1776744b25f0c15d1d3947307bbf9aaf7cefbb7e
  Author: PROJ proj
  Date:   Wed Apr 25 15:24:05 2012 +0800
  second commit
  #
  4)撤消暂存文件 git reset HEAD filename
  # vi teset1.c
  # git add teset1.c
  # git status
  # On branch master
  # Changes to be committed:
  #   (use "git reset HEAD ..." to unstage)
  #
  #    new file:   teset1.c
  #
  # git reset HEAD teset1.c
  # git status
  # On branch master
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    teset1.c
  nothing added to commit but untracked files present (use "git add" to track)
  #
5)撤消当前的修改,如果当前的修改还未提交,不想修改时,可以使用checkout恢复,但是修复仅限于两个状态之间,也就是如果文件当前在COMMIT时,可以直接恢复工作区的版本。如果当前文件在STAGE时,这时只能用RESET来恢复。  # vi test.c
  # git status
  # On branch master
  # Changes not staged for commit:
  #   (use "git add ..." to update what will be committed)
  #   (use "git checkout -- ..." to discard changes in working directory)
  #
  #    modified:   test.c
  #
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    teset1.c
  no changes added to commit (use "git add" and/or "git commit -a")
  # git checkout test.c
  # git status
  # On branch master
  # Untracked files:
  #   (use "git add ..." to include in what will be committed)
  #
  #    teset1.c
  nothing added to commit but untracked files present (use "git add" to track)
  # vi tes
  6)撤消提交操作git commit --amend

页: [1]
查看完整版本: Git基本概念及操作(2)