Git学习笔记

这篇博客详细介绍了Git的安装、版本库创建、版本回退、工作区和暂存区的理解、管理修改,以及远程仓库、分支管理和标签管理等核心概念。通过实例演示了如何操作Git,包括如何处理冲突和多人协作。最后,还涉及了自定义Git配置和搭建Git服务器的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安装Git

ubuntu: $ sudo apt-get install git
windows: 镜像安装

创建版本库

a. 选择一个合适的地方,创建一个空目录:

$ mkdir learngit
$ cd learngit

b. 通过git init命令把这个目录变成Git可以管理的仓库:

$ git init

c. 在git的根目录下(子目录也可以)创建文件readme.txt:

d. 把一个文件放到Git仓库只需要两步:

第一步:用命令git add告诉Git,把文件添加到仓库, 可以同时添加多个文件:
$ git add readme.txt
第二步:用命令git commit告诉Git,把文件提交到仓库:
$ git commit -m "this is a readme file!"
-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。

版本回退

版本回退:
a. 查看仓库的当前状态:

$ git status   

b. 查看修改的内容:

$ git diff

c. 查看仓库操作的历史记录:

$ git log
$ git log --pretty=oneline    #简化输出历史记录
如下所示:
1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL
e475afc93c209a690c39c13a46716e8fa000c366 add distributed
eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file

# 1094a...是commit id,也就是版本号,是通过SHA1计算出来的十六进制数字。

d. 回退到上一个版本:

$ git reset --hard HEAD^
在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
也可以直接通过版本号回退到某个版本:
$ git reset --hard 1094ad    #版本号没有必要写全,前几位就可以Git会自动查找

f. 从旧版本回到新版本。 只能通过commit id,

$ git reflog    #该命令用来记录每一次的命令,可以查找到commit id,
如下所示:
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

工作区和暂存区

a. 工作区: git目录

b. 版本库: 隐藏目录.git即是版本库

版本库 = 暂存区(stage 或 index) + Git自动创建的第一个分支master + HEAD指针(指向master)+ ...

c. 把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

管理修改

git比其他版本控制系统设计地优秀的一个很重要的原因就是: Git跟踪的是修改而非文件。每一次修改都要经过add 和 commit才能生效。

a. 撤回工作区的修改

$ git checkout -- readme.txt    #意思就是,把readme.txt文件在工作区的修改全部撤销;

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

b. 把暂存区的修改退回工作区

$ git reset HEAD readme.txt     
# git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
之后再使用命令 $ git checkout -- readme.txt 撤回工作区的修改

远程仓库

a. 把一个已有的本地仓库与新建的远程新仓库关联。

$ git remote add origin git@github.com:xinhaixufan/git.git    
 
 # origin Git默认的远程仓库的名字

b. 把本地库的所有内容推送到远程仓库

$ git push -u origin master    # 第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令
$ git push origin master

c. 从远程库克隆:

$ git clone git@github.com:xinhaixufan/git.git
$ git clone https://github.com/xinhaixufan/git.git    

# 要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
# Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。

分支管理

a. 创建与合并分支:
每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

$ git branch dev    # 创建dev分支
$ git checkout dev  # 切换到dev分支
$ git checkout -b dev    # 创建并切换到dev分支

$ git branch    # 查看分支
如下:
* dev			# *表示当前分支
  master

$ git merge dev    	   # 将dev分支合并到当前分支。 
$ git merge dev
	Updating d46f35e..b17d20e
	Fast-forward		# Fast-forward 模式表示,这次合并是“快进模式”,也就是直降将master指向dev的当前提交。然而并不是每次提交都可以是Fast-forward。
	 readme.txt | 1 +
	 1 file changed, 1 insertion(+)

$ git branch -d dev    # 删除dev分支

***查看分支:git branch
***创建分支:git branch <name>
***切换分支:git checkout <name>
***创建+切换分支:git checkout -b <name>
***合并某分支到当前分支:git merge <name>
***删除分支:git branch -d <name>

b. 解决冲突问题:
当master分支和dev分支各有新的提交,这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突:
$ git status $该命令会提示哪个文件存在冲突

需要手动修改冲突后再提交,如下:
	Git tracks changes of files.
	<<<<<<< HEAD
	Creating a new branch is quick & simple.
	=======
	Creating a new branch is quick AND simple.
	>>>>>>> feature1
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存:
	Creating a new branch is quick and simple.
此时可以再进行提交

用带参数的git log也可以看到分支的合并情况:

$ git log --graph --pretty=oneline --abbrev-commit

*   cf810e4 (HEAD -> master) conflict fixed
|\  
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/  
* b17d20e branch test
* d46f35e (origin/master) remove test.txt

$ git log --graph    # 可以查看分支合并图
		  --abbrev-commit	# 只显示部分前缀

c. 分支管理策略:
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit

$ git merge --no-ff -m "merge with no-ff" dev    # --no-ff参数,表示禁用Fast forward

d. Bug分支
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,当前正在dev上进行的工作还没有提交:
此时,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$ git stash

之后可以再master分支上创建临时分支issue-101来进行工作,完成之后恢复dev分支的工作现场;
$ git stash list    # 查看工作现场

两种恢复方式:
	$ git stash apply	# 恢复后stash内容不删除
	$ git stash drop	# 删除stash

	$ git stash pop     #恢复的同时删除stash

可以多次stash,恢复的时候:
	$ git stash list	
	$ git stash apply stash@{0}    # 恢复到指定的stash

e. Feature分支
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
但是当该功能取消时,就不需要进行合并,直接删除该分支:

$ git branch -D feature-vulcan		# -D表示强制删除

f. 多人协作
* 多人协作的工作模式通常是这样:
* 首先,可以试图用git push origin 推送自己的修改;
* 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
* 如果合并有冲突,则解决冲突,并在本地提交;
* 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
* 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令:

 $  git branch --set-upstream-to <branch-name> origin/<branch-name>。

小结:

* 查看远程库信息,使用git remote -v;
* 本地新建的分支如果不推送到远程,对其他人就是不可见的;
* 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
* 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
* 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
* 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。

g. Rebase
多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。
每次合并再push后,分支变成了这样:

$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
*   e5e69f1 Merge branch 'dev'
|\  
| *   57c53ab (origin/dev, dev) fix env conflict
| |\  
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/  
* |   12a631b merged bug fix 101
|\ \  
| * | 4c805e2 fix bug 101
|/ /  
* |   e1e9c68 merge with no-ff
|\ \  
| |/  
| * f52c633 add merge
|/  
*   cf810e4 conflict fixed

总之看上去很乱,有强迫症的童鞋会问:为什么Git的提交历史不能是一条干净的直线?

$ git rebase    # 

rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

标签管理

a. 创建标签
* 命令git tag 用于新建一个标签,默认为HEAD,也可以指定一个commit id;

$ git tag v1.0 
$ git tag v0.9 cf810

* 命令git tag -a <tagname> -m "blablabla..." <commit id> 可以指定标签信息;
$ git tag -a v1.0 -m "add tag" HEAD 

* 命令git tag可以查看所有标签。

b. 操作标签
* 删除标签

$ git tag -d v1.0

推送标签至远程

$ git push origin v1.0	# 推送标签v1.0到远程
$ git push origin --tag # 一次性推送全部尚未推送到远程的本地标签

删除远程标签

	** 第一步:先从本地删除
	$ git tag -d v0.9

	** 第二步:从远程删除
	$ git push origin :refs/tags/v0.9

## 命令git push origin <tagname>可以推送一个本地标签;
## 命令git push origin --tags可以推送全部未推送过的本地标签;
## 命令git tag -d <tagname>可以删除一个本地标签;
## 命令git push origin :refs/tags/<tagname>可以删除一个远程标签。

自定义Git

a. 忽略特殊文件:
* 你必须把某些文件放到Git工作目录中,但又不能提交它们,每次git status都会显示Untracked files …
* 在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
* .gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!

忽略文件的原则是:[Git文件忽略原则](https://github.com/github/gitignore)

* 忽略操作系统自动生成的文件,比如缩略图等;
* 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
* 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

最后将.gitignore文件提交到git
如果确实想提交该文件可以强制提交到git

$ git add -f a.class

或者你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查

$ git check-ignore -v a.class

b. 配置别名:

$ git config --global alias st status    # 将status命令配置别名为 st:
配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。

每个仓库的Git配置文件都放在.git/config文件中:

搭建Git服务器

GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台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.
	剩下的推送就简单了。

本文是自己在参考廖雪峰Git教程学习Git时的一些笔记,如有不详之处请移步至廖雪峰Git教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值