
git入门学习与实践(参考廖雪峰教程)
- 世界杯开幕式
- 2025-07-20 15:43:57
- 9761
目录
git入门学习与实践(参考廖雪峰教程)git基础原理git是什么工作区和暂存区git跟踪的是修改而不是文件git远程仓库
git使用git安装创建版本库(Repository)将文件添加至版本库仓库目前状态查看版本回退撤销修改删除git中文件远程仓库添加远程库从远程库克隆从远程仓库抓取
分支管理创建与合并分支解决冲突分支管理策略bug分支Feature分支多人协作
标签管理创建标签操作标签
使用GitHub自定义Git忽略特殊文件配置别名
可以使用SourceTree图形化管理Git
git入门学习与实践(参考廖雪峰教程)
该文章是学习廖雪峰git教程记录与实践,仅供个人学习参考使用 Git Cheat Sheet 极简版总结
git基础原理
git是什么
Git是目前世界上最先进的分布式版本控制系统,是由linux创始人linus花了两周时间自己用C编写的版本控制系统:不但能自动记录每次文件的改动,还可以让其他人协作编辑并说明编辑内容。这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在系统里瞄一眼就可以分布式版本控制系统与集中式版本控制系统
集中式版本控制系统版本库是存放在中央服务器的,每次干活的时候都需要从中央服务器取得最新的版本然后才能开始干活。但其需要互联网才能工作,而且一旦中央存储器的版本出了问题所有人都不能得到最新版本的文件。 分布式版本控制系统没有“中央服务器”,每个人的电脑上都是一个完整的版本库。和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库
工作区和暂存区
工作区(Working Directory) 就是你在电脑里能看到的目录,包含了所有的项目文件,在工作区中进行文件的编辑、创建和删除等操作。比如 learngit 文件夹就是一个工作区
版本库(Repository) 版本库是Git用来存储项目历史记录的地方。它包含了所有的提交记录和分支信息。版本库中有一个隐藏目录.git,这个目录包含了所有的Git管理数据。 Git版本库中存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
暂存区(stage或index) Git中的暂存区是一个临时存储区域,用于保存你在工作区中对文件所做的修改,直到你准备好将这些修改提交到版本库中
HEAD: HEAD是一个指针,指向当前分支的最新提交。通常情况下,HEAD指向的是你正在工作的分支的最新提交。 将一个文件添加至Git版本库时分两步执行
第一步 使用git add命令将修改添加至暂存区
第二步 使用git commit命令将暂存区的内容提交至版本库当前分支
git跟踪的是修改而不是文件
git跟踪的是修改而不是文件
git远程仓库
Git远程仓库是托管在服务器上的版本库,用于存储和管理项目的代码。它允许多个开发者协作开发项目,并保持代码的同步。常见的远程仓库平台有GitHub、GitLab和Bitbucket等。
github远程仓库建立参考这篇文章:VS&GitHub项目联动(上传和克隆),创建你的第一个仓库,小白配置
本地仓库与github之间的传输是通过ssh加密的,所以需要一些设置(具体见链接推文)
创建SSH Key $ ssh-keygen -t rsa -C "youremail@example.com" 在创建好的目录.ssh目录中有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。将自己的公钥添加至github中即可,当你提交时github会将公钥与你提交的私钥进行配对从而确定身份
当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。
git使用
git安装
廖雪峰的官方网站git安装教程及初次使用设置
创建版本库(Repository)
git init
在版本库目标路径(这里是learngit目录)下使用 git init命令把这个目录变成Git可以管理的仓库:
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
如此可以创建一个空的仓库。 在文件中多出了.git目录,是Git来跟踪管理版本库的,若没有看到可用ls -ah命令查看
将文件添加至版本库
git add 文件名 git commit -m “修改内容”
首先可以先编写一个README.md文件,一定要将其放置在learngit目录或其子目录下(win在该目录下右击鼠标,选择open Git Bash here进入命令行界面)。
接下来将README.md放入git仓库中:
第一步,用命令git add告诉Git,把文件添加到仓库:
$ git add README.md
第二步,用命令git commit告诉Git,把文件提交到仓库:
$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 README.md
git commit命令-m后面输入的是本次提交的说明,可以从历史记录里方便地找到改动记录。 为什么Git添加文件需要 add,commit 一共两步呢?因为 commit 可以一次提交很多文件,所以你可以多次 add 不同的文件,比如:
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
仓库目前状态查看
git status git diff git log
我们刚才已经成功提交了README.md文件,现在将其进行修改 然后运行git status即可查看当前仓库状态
$ git status
On branch master
Changes not staged for commit:
(use "git add
(use "git checkout --
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
以上输出说明README.md已经被修改了,但还没有被提交 可以使用git diff命令看到具体修改了那些内容,注意该命令显示了工作区与暂存区之间的差异,有关git diff其他操作看参考这篇文章
$ git diff README.md
diff --git a/README.md b/README.md
index 46d49bf..9247db6 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
可以从上面的命令输出看到,我们在第一行添加了一个distributed单词。
现在提交修改到仓库中
$ git add README.md
使用git status命令查看当前状态:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD
modified: README.md
输出告诉我们,将要被提交的修改包括README.md
$ git commit -m "add distributed"
[master e475afc] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
提交完成后使用git status命令查看当前状态:
$ git status
On branch master
nothing to commit, working tree clean
Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的 使用git log命令可以查看仓库的提交日志,如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:
$ git log --pretty=oneline
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file
每行信息前面的是commit id(版本号)
版本回退
HEAD HEAD^ HEAD^^ HEAD~100 git reset --hard commit_id git reflog
git commit相当于保存了一个快照,一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
在Git中,用HEAD表示当前版本,也就是最新的提交1094adb…(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
现在,我们要把当前版本append GPL回退到上一个版本add distributed,就可以使用git reset命令:
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
--hard会回退到上个版本的已提交状态
$ cat readme.txt
Git is a distributed version control system.
Git is free software.
可以看到文件已经被还原到上个版本 但是原来的版本append GPL已经看不到了想要找回有两个途径
还未关闭命令行窗口:
向上找到那个append GPL的commit id是1094adb…(命令中版本号没必要写全,前几位就可以了,Git会自动去找。),于是就可以指定回到未来的某个版本: $ git reset --hard 1094a
HEAD is now at 83b0afe append GPL
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL: 改为 若已经关闭了命令行窗口:
Git提供了一个命令git reflog用来记录你的每一次命令: $ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
然后就可以得到append GPL的commit id从而回到未来啦
撤销修改
git checkout – file git reset HEAD 既git reset --mixed HEAD
git checkout -- file可以丢弃工作区的修改,有以下两种情况:
文件自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
文件已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
若是已经使用git add 命令提交了文件,想要撤销该提交
用命令git reset HEAD
然后使用git checkout -- file将该文件从工作区撤销
这是因为git reset是一个非常强大的命令,用于撤销更改和回退版本。它有三种主要模式:–soft、–mixed 和 --hard。以下是它们的用法和区别:
git reset --soft commit id: 这个命令会将目前版本回退到指定版本,不会改变当前工作区与暂存区的修改。 仅重置HEAD,不更改索引或工作目录。 例如,git reset --soft HEAD~1 会将当前分支回退到上一个提交,但保留在暂存区和工作区的更改。git reset --mixed commit id(默认模式): 这个命令会将目前版本回退到指定版本,并将暂存区的修改退回工作区(保留暂存区的修改,删除工作区的修改),从而达到撤销修改的效果 重置HEAD和暂存区,但不更改工作目录。 例如,git reset --mixed HEAD~1 会将当前分支回退到上一个提交,并将更改移到工作区。git reset --hard commit id: 这个命令会将目前版本回退到指定版本,并删除暂存区和工作区的所有更改,从而达到版本回退的效果 例如,git reset --hard HEAD~1 会将当前分支回退到上一个提交,并删除所有未提交的更改。 重置HEAD、暂存区和工作目录。
git reset HEAD
删除git中文件
首先新建一个test.txt文件,并提交至git中
$ echo "test" >> test.txt
$ git add test.txt
$ git commit -m "add test.txt"
[master b84166e] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
通常情况下使用rm命令删除文件或拖拽到回收站来删除目录中的文件
$ rm test.txt
现在工作区的文件已经被删除了,版本库中的文件并没有变化 使用git status命令输出如下:
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm
(use "git checkout --
deleted: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
确实要删除该文件并同步删除git版本库中文件
第一步 使用git rm命令删除第二步 使用git commit命令提交 $ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
删错了文件,可以轻松的将误删的文件从版本库中恢复到最新版本
使用版本库中的文件替换工作区的文件(见撤销修改内容) git checkout -- test.txt 或 git reset HEAD test.txt
远程仓库
添加远程库
git remote add origin git@server-name:path/repo-name.git git push -u origin master git push origin master git remote -v git remote rm name
github远程仓库建立参考这篇文章:VS&GitHub项目联动(上传和克隆),创建你的第一个仓库,小白配置
在建立了本地Git仓库后想同步到Github中,并且让两个仓库进行远程同步
1. 首先在github中右上角找到“Create a new repo”按钮,创建一个新的仓库,将仓库名称设为learngit
2. 在
本地的learngit仓库下运行命令:
$ git remote add origin git@github.com:michaelliao/learngit.git
这条命令将本地仓库与远程仓库关联了起来 一定要注意把上面的michaelliao替换成你自己的GitHub账户名,否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的SSH Key公钥不在我的账户列表中。 添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。
3. 首次把本地库的所有内容推送到远程库上:
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
把本地库的内容推送到远程,用git push <远程仓库名> <分支名>命令,实际上是把当前本地分支master推送到远程仓库master分支。 由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
4. 之后的本地提交至远程仓库
使用以下命令即可:
$ git push origin master
5, 删除远程库
如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm
$ git remote -v
origin git@github.com:michaelliao/learn-git.git (fetch)
origin git@github.com:michaelliao/learn-git.git (push)
然后根据名字删除
$ git remote rm origin
此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。
从远程库克隆
用命令git clone克隆一个本地库:
$ git clone git@github.com:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.
这句代码的意思是从 GitHub 上克隆一个名为 gitskills 的仓库到本地。Git 会在你当前的工作目录下创建一个名为 gitskills 的文件夹,并将远程仓库的所有内容克隆到这个文件夹中。让我们逐步解析这句代码:
git clone:这是 Git 命令,用于克隆一个远程仓库到本地。克隆操作会创建一个包含远程仓库所有文件和历史记录的本地副本。git@github.com:michaelliao/gitskills.git:这是远程仓库的地址,使用的是 SSH 协议。具体来说:
git@github.com:这是 GitHub 的 SSH 地址,表示你通过 SSH 协议连接到 GitHub。michaelliao:这是 GitHub 用户名,表示这个仓库属于用户 michaelliao。gitskills.git:这是仓库的名称,表示你要克隆的具体仓库。
从远程仓库抓取
注:抓取命令涉及到下节分支管理内容,可在了解分支管理内容之后学习
git pull 命令用于从远程获取代码并合并本地的版本。
git pull 其实就是 git fetch 和 git merge 的简写,先从远程仓库获取最新的提交记录,然后将这些提交记录合并到你当前的分支中。
其中:
git fetch [远程仓库名] “抓取”(fetch)是指从远程仓库获取更新的内容并下载到本地仓库。命令不会自动将远程更改合并到当前分支,只是将它们下载到本地供你选择何时合并。git merge [dev] 则是将dev分支合并至当前分支下
git pull命令格式如下:
git pull [远程仓库名] [分支名]
分支管理
在git中,每次提交git都将他们串成一根时间线,既一个分支主分支既master分支HEAD指针严格来说不是指向提交,而是指向master,master指向提交,所以HEAD指向的就是当前分支因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。
创建与合并分支
git checkout -b dev git branch git checkout master git merge dev git branch -d dev
仅有主支线 初始状态下只有master一条主分支,git用master指向最新的提交,再用HEAD指向master就可以确定当前的分支以及提交点 每次提交master 分支都会向前移动一步,主支线越来越长,HEAD也随之移动
创建新的分支dev 创建新的分支dev时,git新建了一个指针dev指向与master相同的提交,然后将HEAD指针指向dev指针表示当前分支在dev分支上 创建dev分支并切换到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
git checkout 命令用于切换分支或恢复工作区文件。以下是一些常见的用法
1. 切换到已有分支:
git checkout
git checkout同一个命令,有两种作用,确实有点令人迷惑。实际上,切换分支命令用switch更科学。因此,最新版本的Git提供了新的git switch命令来切换分支:
创建并切换到新的dev分支,可以使用: $ git switch -c dev直接切换到已有的master分支,可以使用: $ git switch master
然后使用git branch命令列出所有分支并查看当前分支:
$ git branch
* dev
master
至此新分支dev创建完成
3. 修改提交 dev 分支
从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,HEAD指针更随dev变化,而master指针不变: 修改README.md并提交至dev分支
$ git add README.md
$ git commit -m "branch test"
[dev b17d20e] branch test
1 file changed, 1 insertion(+)
4. 将 dev 分支合并至 master 分支
直接把master指向dev的当前提交,再将HEAD指针指向master就完成了合并:
切换回master分支:
$ git checkout master
Switched to branch 'master'
此时刚才的提交任然在dev分支上,而master分支此时的提交点并没有变: 需要将dev分支的工作合并到master上:
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge命令用于合并指定分支到当前分支。
5. 合并完成后,就可以将dev分支删除了
$ git branch -d dev
Deleted branch dev (was b17d20e).
删除后查看branch
$ git branch
* master
如果有远程库还需将本地库上传到远程库中:
$ git push origin master
解决冲突
若一个文件在两个分支中均被修改,在两个分支进行合并时就会发生冲突,需要手动将发生冲突的文件修改后重新提交即可解决冲突。
新建一个feature1分支,并在该分支上修改README.md提交切换到master分支并在该分支上修改README.md提交现在,master分支和feature1分支各自都分别有新的提交,变成了这样: 此时合并分支会出现冲突
$ git merge feature1
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
可以看到现在README.md中内容被git用<<<<<<<,=======,>>>>>>>标记出来
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
将README.md做如下修改后重新提交
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
Creating a new branch is quick and simple.
现在master分支和feature1分支变成了下图所示: 用带参数的git log --graph也可以看到分支的合并情况
最后删除feature1分支
分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
$ git merge --no-ff -m "merge with no-ff" dev
不使用Fast forward模式,merge后就像这样: 在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
bug分支
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick
Feature分支
开发一个新功能,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,需要通过git branch -D
多人协作
当从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin
可以使用git remote -v查看远程仓库信息
推送分支
如将dev分支推送至远程仓库
$ git push origin dev
不一定所有分支都得推送至远程仓库
master分支是主分支,因此要时刻与远程同步;dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。 抓取分支
当在远程库中clone时,只能看到master 分支,无法看到远程库中的dev分支,如果要在dev分支上开发可以使用git checkout命令建立远程库的dev分支到本地的dev分支:
$ git checkout -b dev origin/dev
git checkout
现在就可以在dev分支上进行修改,并将修改推送至origin/dev分支
$ git push origin dev
但当多人向origin/dev分支推送时,推送可能会有冲突,就需要将远程分支抓取下来手动解决冲突,解决的方法和分支管理中的解决冲突完全一样。解决后再推送:
$ git pull
因此,多人协作的工作模式通常是这样:
首先,可以尝试用git push origin
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
标签管理
创建标签
命令git tag
操作标签
因为创建的标签都只存储在本地,不会自动推送到远程。如果要推送某个标签到远程,使用命令git push origin
使用GitHub
在GitHub上,可以任意Fork开源仓库,从而将仓库克隆至自己账号下;只有从自己账号下克隆的仓库才可以推送修改,如果从作者的仓库地址克隆,因为没有权限,将不能推送修改。 如果你想修复克隆仓库中的一个bug,或者新增一个功能,立刻就可以开始干活,干完后,往自己的仓库推送。 如果你希望官方库能接受你的修改,你就可以在GitHub上发起一个pull request。当然,对方是否接受你的pull request就不一定了。
自定义Git
忽略特殊文件
忽略某些文件时,需要编写.gitignore。.gitignore文件本身要放到版本库里,并且可以对.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 config --global alias.st status
表示使用可以st代表status
配置Git的时候,加上–global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
可以使用SourceTree图形化管理Git
