git基础

mac2026-05-13  9

Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持

Git 与 SVN 区别

Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。

如果你是一个具有使用 SVN 背景的人,你需要做一定的思想转换,来适应 Git 提供的一些概念和特征。

Git 与 SVN 区别点:

1、Git 是分布式的,SVN 不是:这是 Git 和其它非分布式的版本控制系统,例如 SVN,CVS 等,最核心的区别。

2、Git 把内容按元数据方式存储,而 SVN 是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等文件夹里。

3、Git 分支和 SVN 的分支不同:分支在 SVN 中一点都不特别,其实它就是版本库中的另外一个目录。

4、Git 没有一个全局的版本号,而 SVN 有:目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征。

5、Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

我们先来理解下 Git 工作区、暂存区和版本库概念:

工作区、版本库中的暂存区和版本库之间的关系如下

基本概念

工作区:workspace。就是你在电脑里能看到的目录。暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。git add 添加到暂存区。版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。版本库包含暂存区。master:标记为 "master" 的是 master 分支所代表的目录树。 图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage/index),标记为 "master" 的是 master 分支所代表的目录树。图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。当执行 git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。当执行 git checkout . 或者 git checkout -- <file> 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。

git文件提交过程:

local reository  本地分支,git commit 添加到本地分支remote repository 远程分支,git push 推送到远程分支

git重要命令的使用

Git 常用的是以下 6 个命令:git clone、git push、git add 、git commit、git checkout、git pull,后面我们会详细介绍。

1. git init 

git init

git init 命令用来初始化一个 Git 仓库,Git 的很多命令都需要在 Git 的仓库中运行。Git 仓库会生成一个 .git 目录,该目录包含了资源的所有元数据,其他的项目目录保持不变

2.设置本机的账户和邮箱一个人一个身份之别

git config --global user.name "xxxxx" git config --global user.email "xxxxx" #查看 git config user.name git config user.email

 git config --list 查看所有的属性

3. git add

提交代码到暂存区(Index)

可以用它开始跟踪新文件,并放到暂存区,新建的文件尚未加到git的追踪中,需要使用git add 文件名来追踪或者把已跟踪的被修改的文件放到暂存区 //一个 git add name //所有 git add .

4. git commit 提交

提交代码到本地分支(local reository)

git commit  -m "注释"                  #一次提交多个文件git commit  name  -m "注释"        #一次提交一个文件  $ git commit -m "提交readme文件" [master (root-commit) eb8683b] 提交readme文件 1 file changed, 3 insertions(+) create mode 100644 README

会返回当前是在哪个分支(master)提交的

跳过暂存区提交

不用git add 直接进入 git commit,注意是已经跟踪过的,未使用git add跟踪的不可以

Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤

$ git commit -a -m "不add直接提交" [master 60cc9af] 不add直接提交 1 file changed, 2 insertions(+), 1 deletion(-)

5.git status检查当前文件状态  

git status 详细版 git status -s 简版

#状态一 #On branch master #nothing to commit, working directory clean #所有已跟踪文件在上次提交后都未被更改过

#状态二 #Untracked files #新文件,还未被跟踪, 需要git add

#状态三 #Changes to be committed #文件已被跟踪,并处于暂存状态 已经git add 还没git commit

#状态四 #Changes not staged for commit #说明已跟踪文件的内容发生了变化,但还没有放到暂存,需要git add

6.git diff 

比较文件的不同,即暂存区和工作区的差异。

执行 git diff 来查看执行 git status 的结果的详细信息。

git diff       比价暂存区和工作区的差异git diff --cached  比较暂存区和HEAD的差异git diff HEAD  比较工作区和HEAD的差异

1.尚未写入暂存区的改动(即AM):git diff

2.查看已写入暂存区的改动: git diff --cached

3.查看已写入暂存区的与未写入暂存区的所有改动:git diff HEAD

3.显示摘要而非整个 diff:git diff --stat

不带参数的调用

git diff filename 这种是比较 工作区和暂存区

比较暂存区与最新本地版本库

git diff --cached filename

比较工作区和最新版本

git diff HEAD filename

比较工作区与指定的 commit -id 的差异

git diff commit-id filename

比较暂存区与指定 commit-id 的差异

git diff --cached commit-id filename

比较两个 commit -id 的差异

git diff commit-id commit-id

7.git log 查看历史提交记录

git log -显示从最近到最远的提交日志,主要用于回退版本

git blame <file> -以列表形式查看指定文件的历史修改记录。

git log 查看日志

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数或者加 --oneline

git log --pretty=oneline

 --graph 查看历史中什么时候出现了分支、合并。以下为相同的命令,开启了拓扑图选项

git log --graph

--reverse 逆向显示所有日志

git log --reverse

git log --author 查找指定用户的提交日志可以使用命令:例如,比方说我们要找 Git 源码中 guxilong提交的部分,只要最近5条

git log --author=guxilong --oneline -5

--since 和 --before,指定开始结束日期,但是你也可以用 --until 和 --after。

例如,如果我要看 Git 项目中三周前且在四月十八日之后的所有提交,我可以执行这个(我还用了 --no-merges 选项以隐藏合并提交):

如果要查看指定文件的修改记录可以使用 git blame 命令 

git blame <file>

8. git reset 回退版本

在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

从暂存区回滚 (一定要看,回滚之前请保存或者提交代码。切勿在回滚的时候有未提交到分支的代码,会发生不可逆转的损失)

git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commit或git add时的状态。

回滚到指定版本号

git回退到上个版本

git reset --hard HEAD^

回退到前3次提交之前,以此类推,回退到n次提交之前

git reset --hard HEAD~3

回滚到指定的版本号

git log 找到指定的commit号git reset --hard commit号   本地仓库和暂存区都回滚到commit号提交

版本号没必要写全,前几位就可以了,Git会自动去找

Git提供了一个命令git reflog用来记录你的每一次命令: git reflog

9.git rm  删除工作区文件

git rm FileName

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部分(也就是未暂存清单),然后再次提交

 git rm --cached FileName

另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆 .a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可

git checkout -- test.txt

如果删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本。

git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

 注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!

git mv 移动或重命名工作区文件

git mv 命令用于移动或重命名一个文件、目录或软连接。

git mv [file] [newfile]

如果新但文件名已经存在,但还是要重命名它,可以使用 -f 参数:

git mv -f [file] [newfile]

我们可以添加一个 README 文件(如果没有的话):

$ git add README

然后对其重命名:

$ git mv README README.md $ ls README.md

10.忽略某些文件

$cat .gitinnore *.[oa] *~

第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的,我们用不着跟踪它们的版本。第二行告诉 Git 忽略所有以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。

文件 .gitignore 的格式规范如下:

所有空行或者以注释符号 # 开头的行都会被 Git 忽略。可以使用标准的 glob 模式匹配。匹配模式最后跟反斜杠(/)说明要忽略的是目录。要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(*)匹配零个或多个任意字符;[abc]匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)

我们再看一个 .gitignore 文件的例子:

# 此为注释 – 将被 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 版本 1.8.2 以上已经可以使用。

11.远程仓库

由于你的本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以我们需要配置验证信息:

使用以下命令生成 SSH Key:

$ ssh-keygen -t rsa -C "自己的邮箱"

后面的 自己的邮箱 改为你在 Github 上注册的邮箱,之后会要求确认路径和输入密码,我们这使用默认的一路回车就行。

成功的话会在 ~/ 下生成 .ssh 文件夹,进去,打开 id_rsa.pub,复制里面的 key。

回到 github 上,进入 Account => Settings(账户配置)。

左边选择 SSH and GPG keys,然后点击 New SSH key 按钮,title 设置标题,可以随便填,粘贴在你电脑上生成的 key。

添加成功后界面如下所示

为了验证是否成功,输入以下命令:

拉取项目,git pull origin master = git fetch origin + git merge origin/master

 git clone 克隆项目

git clone git://github.com/schacon/simplegit-progit.git

使用 git clone 从现有 Git 仓库中拷贝项目。行该命令后,会在当前目录下创建一个名为simplegit-progit的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录

克隆仓库的命令格式为:

git clone <url>

如果我们需要克隆到指定的目录,可以使用以下命令格式:

git clone <url> <file> 参数说明: url:Git 仓库。 file:本地目录。

添加远程仓库地址

git remote add origin url

查看当前的远程库

git remote

git remote -v

要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库:

也可以加上 -v 选项(译注:此为 --verbose 的简写,取首字母),显示对应的克隆地址:

gu_xi@PC-GUXILONG MINGW64 /d/software/projectspace/ticgit (master) $ git remote origin gu_xi@PC-GUXILONG MINGW64 /d/software/projectspace/ticgit (master) $ git remote -v origin git://github.com/schacon/ticgit.git (fetch) origin git://github.com/schacon/ticgit.git (push)

 git remote show [remote-name] 

我们可以也通过命令 git remote show [remote-name] 查看某个远程仓库的详细信息,比如要看所克隆的 origin 仓库,可以运行:

$ git remote show origin * remote origin URL: git://github.com/schacon/ticgit.git Remote branch merged with 'git pull' while on branch master master Tracked remote branches master ticgit

除了对应的克隆地址外,它还给出了许多额外的信息。它友善地告诉你如果是在 master 分支,就可以用 git pull 命令抓取数据合并到本地。另外还列出了所有处于跟踪状态中的远端分支。

上面的例子非常简单,而随着使用 Git 的深入,git remote show 给出的信息可能会像这样:

$ git remote show origin * remote origin URL: git@github.com:defunkt/github.git Remote branch merged with 'git pull' while on branch issues issues Remote branch merged with 'git pull' while on branch master master New remote branches (next fetch will store in remotes/origin) caching Stale tracking branches (use 'git remote prune') libwalker walker2 Tracked remote branches acl apiv2 dashboard2 issues master postgres Local branch pushed with 'git push' master:master

远程仓库的删除和重命名

在新版 Git 中可以用 git remote rename 命令修改某个远程仓库在本地的简称,比如想把 pb 改成 paul,可以这么运行:

$ git remote rename pb paul $ git remote origin paul

注意,对远程仓库的重命名,也会使对应的分支名称发生变化,原来的 pb/master 分支现在成了 paul/master。

碰到远端仓库服务器迁移,或者原来的克隆镜像不再使用,又或者某个参与者不再贡献代码,那么需要移除对应的远端仓库,可以运行 git remote rm 命令:

$ git remote rm paul $ git remote origin

12. 推送至远程仓库

 git push [remote-name] [branch-name]。如果要把本地的 master 分支推送到 origin 服务器上(再次说明下,克隆操作会自动使用默认的 master 和 origin 名字),可以运行下面的命令:

$ git push origin master

只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。

git push -u origin master     -u的意思是默认把本地master和远程的master关联上去,下次就直接git push

13. 从远程仓库拉取数据(更新本地代码)

git pull = git fetch + git merge 尽量用git getch + git merge

git fetch不会进行合并执行后需要手动执行git merge合并分支,而git pull拉取远程分之后直接与本地分支进行合并

git pull <远程主机名> <远程分支名>:<本地分支名>

例如执行下面语句:

git pull origin master:brantest 将远程主机origin的master分支拉取过来,与本地的brantest分支合并

git pull origin mastes

表示将远程origin主机的master分支拉取过来和本地的当前分支进行合并。

gu_xi@PC-GUXILONG MINGW64 /d/software/projectspace/e3mall (master) $ git fetch From https://github.com/guxilong/e3mall 43e1185..fb72f7f master -> origin/master gu_xi@PC-GUXILONG MINGW64 /d/software/projectspace/e3mall (master) $ git merge Updating 43e1185..fb72f7f Fast-forward README.md | 1 + test1.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 test1.txt

14.git 分支管理

git  branch <name>          创建分支git branch                         查看本地分支git branch -a                    查看所有分支git branch -d <name>     删除分支git branch -D <name>     强制删除某分支git checkout <name> 或者git switch <name>  切换到name分支git checkout -b <name> 或者git switch -c <name> 创建dev分支,然后切换到dev分支git merge <name>          合并某分支到当前分支 //查看分支,*指当前分支位置 $ git branch * master //创建分支 $ git branch testing //创建 $ git branch //查看 * master testing //新创建的分支 //切换分支 $ git checkout testing Switched to branch 'testing' //创建并切换分支 $ git checkout -b dev Switched to a new branch 'dev' /***/ git checkout命令加上-b参数表示创建并切换,相当于以下两条命令: $ git branch dev $ git checkout dev /***/ /*如果我们创建了一个分支,在该分支的上移除了一些文件 test.txt,并添加了 runoob.php 文件,然后切换回我们的主分支,删除的 test.txt 文件又回来了,且新增加的 runoob.php 不存在主分支中。 使用分支将工作切分开来,从而让我们能够在不同开发环境中做事,并来回切换。 一旦某分支有了独立内容,你终究会希望将它合并回到你的主分支。 你可以使用以下命令将任何分支合并到当前分支中去:*/ $ git branch * master $ git merge newtest //以上实例中我们将 newtest 分支合并到主分支去 //删除分支 $ git branch -d newtest Deleted branch newtest (was c1501a2).

注意在创建好分支后再切换分支的时候其实已经把主分支的内容已经到了支分支(这里是dev分支)里面了。在此分支上工作完后,需要切回master分支才能合并到master分支。

 

最新回复(0)