Python: 版本控制Git
- TAGS: Python
git服务搭建
Gogs
Go语言开发的Git服务器
Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。
安装步骤
1.新建用户 2.下载源码进行编译Compiler/下载预编译二进制文件 3.安装 4.调整配置 5.配置nginx反向代理 6.添加服务Services及开机启动
注意,这里默认你已经安装并配置好了MySQL和nginx,如果没有,请自行查找如何安装和配置这些依赖Dependencies。当然你也可以使用SQLite数据库。
安装
官方文档:https://gogs.io/docs/installation
软件依赖
在安装 Gogs 之前,您需要先安装基本环境
apt install git -y
Mysql安装
# 查看包 apt list 'mariadb*' #安装 apt install mariadb-server systemctl start mariadb #修改绑定端口 vim /etc/mysql/mariadb.conf.d/50-server.cnf bind-address = 0.0.0.0 systemctl restart mariadb #添加远程用户 mysql MariaDB [(none)]> create user root@'%' identified by '123456'; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; SHOW GRANTS FOR 'root'@'%'; #grant all on *.* to 'tom'@'%' identified by 'tom'; 初始化脚本提高安全性 运行脚本:mariadb-secure-installation #mysql_secure_installation 设置数据管理员root口令 禁止root远程登录 删除anonymous用户帐号 删除test数据库
Gogs服务以git用户运行
adduser git # useradd git su - git wget https://github.com/gogs/gogs/releases/download/v0.13.3/gogs_0.13.3_linux_amd64.tar.gz tar xf gogs_0.13.3_linux_amd64.tar.gz cd gogs/ └─$ ll total 79344 -rwxr-xr-x 1 git git 81220896 Jun 9 09:38 gogs -rw-r--r-- 1 git git 1054 Jun 9 09:38 LICENSE -rw-r--r-- 1 git git 6626 Jun 9 09:38 README.md -rw-r--r-- 1 git git 5385 Jun 9 09:38 README_ZH.md drwxr-xr-x 7 git git 4096 Jun 9 09:38 scripts
初始化数据库
mysql -uroot -p < scripts/mysql.sql # 其实就是创建了一个gogs的库 # 为gogs库创建mysql用户gogs,并授权 grant all on gogs.* to 'gogs'@'%' identified by 'gogs'; flush privileges;
配置
参考官方文档: https://gogs.io/docs/installation/configuration_and_run
概述
名称 | 描述 |
APP_NAME | 应用名称,可以改成您的组织或公司名称 |
RUN_USER | 运行应用的用户名称,我们建议您使用 git,但如果您在个人计算机上运行 Gogs,请修改为您的系统用户名称。如果没有正确设置这个值,很可能导致您的应用崩溃 |
服务器 (server)
名称 | 描述 |
HTTP_ADDR | 应用 HTTP 监听地址 |
HTTP_PORT | 应用 HTTP 监听端口号 |
DOMAIN | 服务器域名,会影响 SSH clone 地址 |
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
仓库(repository)
名称 | 描述 |
ROOT | 用户仓库储存根目录,必须为绝对路径,默认为 ~/<user name>/gogs-repositories |
数据库(database)
名称 | 描述 |
DB_TYPE | 数据库类型,可以是 mysql、postgres、mssql 或 sqlite3 |
HOST | 数据库主机地址与端口 |
NAME | 数据库名称 |
USER | 数据库用户名 |
PASSWD | 数据库用户密码 |
安全 (security)
名称 | 描述 | |
INSTALL_LOCK | 用于指示是否允许访问安装页面(该页面可以设置管理员帐号,因此该选项非常重要) | |
SECRET_KEY | 全局的加密密钥,务必修改该值以确保您的服务器安全(会在每次安装时自动生成随机字符串) |
默认配置都保存在 conf/app.ini,永远不需要 编辑它。该文件从 v0.6.0 版本开始被嵌入到二进制中。
自定义配置文件。不需要创建,服务启动后会自动创建。
在gogs目录下建立custom/conf/app.ini配置文件
mkdir -p custom/conf
cd custom/conf
touch app.ini
custom/conf/app.ini内容如下
APP_NAME = cici RUN_USER = git RUN_MODE = dev [server] HTTP_ADDR = 0.0.0.0 HTTP_PORT = 3000 [database] DB_TYPE = mysql HOST = 127.0.0.1:3306 NAME = gogs USER = gogs PASSWD = gogs [security] INSTALL_LOCK = fal SECRET_KEY = www.m
启动gogs
cp /home/git/gogs/scripts/systemd/gogs.service /lib/systemd/system/ systemctl enable --now gogs └─# systemctl cat gogs # /usr/lib/systemd/system/gogs.service [Unit] Description=Gogs After=syslog.target After=network.target After=mariadb.service mysql.service mysqld.service postgresql.service memcached.service redis.service [Service] # Modify these two values and uncomment them if you have # repos with lots of files and get an HTTP error 500 because # of that ### #LimitMEMLOCK=infinity #LimitNOFILE=65535 Type=simple User=git Group=git WorkingDirectory=/home/git/gogs ExecStart=/home/git/gogs/gogs web Restart=always Environment=USER=git HOME=/home/git # Some distributions may not support these hardening directives. If you cannot start the service due # to an unknown option, comment out the ones not supported by your version of systemd. ProtectSystem=full PrivateDevices=yes PrivateTmp=yes NoNewPrivileges=true [Install] WantedBy=multi-user.target └─# ss -ntlp State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 4096 *:3000 *:* users:(("gogs",pid=4957,fd=3))
浏览器访问 http://192.168.226.130:3000/install 配置首次运行安装程序
- 数据库设置
- 数据库类型:mysql 账号密码等
- 应用基本设置
- 应用名称、仓库根目录、域名等
- 可选设置
- 服务器和其它服务设置
- 勾选 禁用 Gravatar 服务,这是头像但要翻墙
- 管理员帐号设置(可跳转登录页时再填写)
- 服务器和其它服务设置
- 点击 立即运行
跳转到登录页。需要注册第一个用户,这个用户直接成为管理员账户。
git
由来
Linux内核代码需要版本管理工具管理代码,2002年开始,使用的是BitMover公司的BitKeeper这个商用软件。但是Linux社区崇尚的是自由软件相悖。
- 2005年,Andrew Tridgell对BitKeeper的协议进行逆向工程,BitKeeper作者决定收回无偿使用授权。磋商无果,Linus又找不到合适的版本管理工具,决定自行开发分布式版本管理工具,一个月后,Linux内核代码被Git接管。
- 2008年,基于WEB使用Git进行版本控制的软件托管服务的网站GitHub上线。
- 2016年5月9日,11年后,BitKeeper开源,发布在了GitHub上。
- 2018年6月4日,微软宣布,通过75亿美元的股票交易收购代码托管平台GitHub。
安装
下载对应操作系统的Git客户端版本
Linux
从RHEL上安装非常简单
yum install git
windows
下载对应的32位或者64版本,点击安装即可
git --version 查看版本号
概念

名称 | |
---|---|
Repository 仓库、版本库 | git初始化后,会在当前目录生成一个 .git 目录,这就是版本库 |
Workspace工作空间、工作区 | .git 文件所在的目录就是工作区,一般是项目的根目录 |
index索引 | 介于工作区和版本库之间,暂存修改的 |
remote 远程版本库 | 网络上的另一个版本库,可以和本地库交互 |
使用
初始化一个版本库
mkdir test cd test # 初始化库 git init └─$ ls .git config description HEAD hooks info objects refs
- 在当前目录中增加了一个.git目录,不要自行修改这个目录里面的文件
- 当前目录一般是项目的根目录
添加文件
创建一个html文件
echo 'line 1' > readme echo '<html><head><title>test</title></head><body>My Website</body></html>' > index.html
查看状态 git status
└─$ git status On branch master No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) index.html readme nothing added to commit but untracked files present (use "git add" to track) └─$ git status -s ?? index.html ?? readme
-s, -short短格式输出
可看到当前有一个刚创建的文件为红色,需将跟踪文件使用 add
命令添加到暂存区 index
,给git管理
添加 add
1、单个文件添加
# 1加入管理 2 记录变化 3 只是进入到暂存区,不算提交 git add <filename>
这一步是把文件的当前变化添加到索引中,也就是以后这个文件需要版本库来跟踪管理,注意这不是提交。
此时,文件还可以继续修改,还可以添加新的被跟踪文件,一定要add才能把这些改变加入到索引中
└─$ git add readme └─$ git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: readme Untracked files: (use "git add <file>..." to include in what will be committed) index.html
2、批量添加
git add . #.点号,代表当前目录,这条命令将递归添加当前目录及其子目录所有文件 #只要是目录,就会递归添加改目录下的文件和子目录 └─$ git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: index.html new file: readme
Git的文件分类
- 追踪的Tracked,已经加入版本库的文件
- 未追踪的Untracked,未加入到版本库的未被管理的文件
- 忽略的Ignored,git不再关注的文件,例如一些临时文件
.gitignore=文件中,目录以/结尾,行起始的!的是取反
.gitignore内容如下
*.ipynb __pycache__/ .python-version
忽略文件不需要自己写,Python的已经有写好 https://github.com/github/gitignore/blob/master/Python.gitignore
其他语言的在这里找 https://github.com/github/gitignore
wget -O .gitignore https://github.com/github/gitignore/blob/main/Python.gitignore
提交代码 git commit
└─$ git commit Author identity unknown *** Please tell me who you are. Run git config --global user.email "[email protected]" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: unable to auto-detect email address (got 'jasper@kali.(none)')
配置本地用户名和邮箱
这是个好习惯,建议这时候一定要加上
git config --global user.name "my" git config --global user.email "[email protected]" # 这些内容对应~/.gitconfig文件,是 用户级别 的配置文件 $ cat ~/.gitconfig [user] name = my email = [email protected] # 命令显示 git config --list git config --global user.name git config --global user.email
#1命令行方式提交 git commit -m "firstcommit" #2可视化界面提交 git commit filename #操作如同Linux,i=输出,wq为保存退出 #在红色区域输出提交时的说明,需描述本次提交改动了什么文件,什么内容。
commit 命令:提交更改到版本库
- -m:填写本次日志消息,必须写。工作中,程序应该对每一次提交写明做了什么改动。
修改后再次提交
sed -i -r 's@(<body>)(.*)(</body>)@\1Welcome to \2\3@' index.html └─$ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a") #再提交 └─$ git commit -m "Second Commit" On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a")
看上面的信息,commit之后发现,变动的文件index.htm并没有提交
git add index.html #再提交,提交成功 └─$ git commit -m "Second Commit" [master 946c993] Second Commit 1 file changed, 1 insertion(+), 1 deletion(-)
文件的生命周期

- 文件add后,就成为可跟踪文件的未修改状态unmodified,修改后,文件就变成modified状态。
- 再次add后,将变化提交到索引,状态变为staged,这才能提交。提交成功,文件状态从staged变回unmodified。
git的提交
git的提交分为两个步骤:
- 暂存变更:add作用是把新文件或者文件新的改动添加到一个暂存区stage,也就是加入到index中
- 提交变更:commit提交的是暂存区中的改动,而不是物理文件目前的改动,提交到当前分支,默认是master分支
也可以使用下面命令,将两步合成一步
git commit readme
如果改动了一批文件,一个个写名字很麻烦,使用下面的命令
git commit -a
- -a,–all 会把所有跟踪的文件的改动自动暂存,然后commit。上面命令未提交message,会出现一个类似vi命令的操作界面,需要编写message之后,才行。
也可以使用下面的命令,把message信息一并填写了。
git commit -a -m "message"
增补
第二次提交后,忘记修改文件内容或者忘记增加文件,又不想增加提交记录。
touch about.htm git add about.htm #重新生成提交记录,替换当前分支最近的提交 git commit -a --amend -m 'again commit'
- –amend 修改,通过创建一个新的commit来replace当前分支的顶部。也可以在命令中继续使用-m选项直接提交message。
git log
查看一下版本库里面提交的历史记录
diff 比较
git diff
查看被跟踪文件未暂存的修改,比较暂存区和工作区git diff --cached
查看被跟踪文件暂存的修改,比较暂存区和上一次commit的差异git diff HEAD
查看被跟踪文件,比较工作区和上一次commit的差异。HEAD指代最后一次commit
echo "line 2" >> readme # modified状态 └─$ git diff # 比较暂存区和工作区 diff --git a/readme b/readme index 89b24ec..7bba8c8 100644 --- a/readme +++ b/readme @@ -1 +1,2 @@ line 1 +line 2 └─$ git diff --cached #比较暂存区和上一次commit的差异 └─$ git diff HEAD # 比较工作区和上一次commit的差异 diff --git a/readme b/readme index 89b24ec..7bba8c8 100644 --- a/readme +++ b/readme @@ -1 +1,2 @@ line 1 +line 2
HEAD
- HEAD可以看做是一个游标,一般是指向当前分支最后一次提交。
- HEAD的值存储在.git/HEAD中。
HEAD
,指代最后一次commitHEAD^
,指代上一次提交HEAD^^
,指代上上一次提交- 上n次提交,表示为
HEAD~n
└─$ git diff HEAD^ readme diff --git a/readme b/readme index 89b24ec..7bba8c8 100644 --- a/readme +++ b/readme @@ -1 +1,2 @@ line 1 +line 2
检出
checkout 用于(创建)切换分支,或恢复工作区文件。
注意:checkout会重写工作区,这个命令还是较为危险的
命令 | 说明 |
---|---|
git checkout |
列出暂存区可以被检出的文件 |
git checkout file |
从暂存区检出文件到工作区,就是覆盖工作区文件,可指定检出的文件。但是不清除stage |
git checkout commit file |
检出某个commit的指定文件到暂存区和工作区 |
git checkout . |
取出暂存区的所有文件到工作区 |
#不小心写错了,工作区内容覆盖了 echo > readme # 清除工作区文件内容 git checkout readme # 从暂存区检出到工作区,工作区文件有了内容 git checkout HEAD readme # 使用当前分支的最后一次commit检出覆盖暂存区和工作区 # 下面3条命令结果一致了 $ git diff $ git diff --cached $ git diff HEAD
命令 | 说明 |
---|---|
git reset |
列出将被reset的文件 |
git reset file |
重置文件的暂存区,和上一次commit一致,工作区不影响 |
git reset --hard |
重置暂存区与工作区,与上一次commit保持一致 |
echo "<html>Welcome about</html>" > index.html git add index.html # 添加到暂存区 git reset index.html # 使用最后一次提交覆盖暂存区 cat index.html # 工作区文件有内容 git add index.html # 添加到暂存区 git reset --hard # 重置暂存区与工作区为上一次commit cat index.html # 工作区文件
命令 | 说明 |
---|---|
git reflog |
显示commit的信息,只要HEAD发生变化,就可以在这里看到 |
git reset --soft commit |
重置当前分支的HEAD为指定commit,但暂存区区和工作区不变 |
git reset commit |
重置当前分支的HEAD为指定commit,同时重置暂存区,但工作区不变 |
git reset --hard [commit] |
重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致 |
git reset --keep [commit] |
重置当前HEAD为指定commit,但保持暂存区和工作区不变 |
#创建一个新文件 └─$ echo 'print("HelloWorld!")' > app.py └─$ git add . └─$ git commit -m "commit add app.py" [master 1e2131d] commit add app.py 1 file changed, 1 insertion(+) create mode 100644 app.py # 重置暂存区和工作区,与指定commmit一致 └─$ git reset --hard 946c9936f HEAD is now at 946c993 Second Commit └─$ ll total 8 -rw-rw-r-- 1 jasper jasper 80 Sep 26 17:44 index.html -rw-rw-r-- 1 jasper jasper 7 Sep 26 17:50 readme └─$ git reflog # 查看log 946c993 (HEAD -> master) HEAD@{0}: reset: moving to 946c9936f 1e2131d HEAD@{1}: commit: commit add app.py 7845649 HEAD@{2}: reset: moving to HEAD 7845649 HEAD@{3}: reset: moving to HEAD 7845649 HEAD@{4}: commit (amend): 2 append 2.1 767e203 HEAD@{5}: commit: add gitignore 946c993 (HEAD -> master) HEAD@{6}: commit: Second Commit cf4ad40 HEAD@{7}: commit (initial): create files # 指定到之前的提交 └─$ git reset --hard 1e2131d HEAD is now at 1e2131d commit add app.py └─$ ll total 12 -rw-rw-r-- 1 jasper jasper 21 Sep 26 17:53 app.py -rw-rw-r-- 1 jasper jasper 80 Sep 26 17:44 index.html -rw-rw-r-- 1 jasper jasper 16 Sep 26 17:53 readme └─$ git reflog 1e2131d (HEAD -> master) HEAD@{0}: reset: moving to 1e2131d 946c993 HEAD@{1}: reset: moving to 946c9936f 1e2131d (HEAD -> master) HEAD@{2}: commit: commit add app.py 7845649 HEAD@{3}: reset: moving to HEAD 7845649 HEAD@{4}: reset: moving to HEAD 7845649 HEAD@{5}: commit (amend): 2 append 2.1 767e203 HEAD@{6}: commit: add gitignore 946c993 HEAD@{7}: commit: Second Commit cf4ad40 HEAD@{8}: commit (initial): create files
reset操作,要慎重
撤销
git revert
#修改并提交,发现错误,想要倒回去一个版本 echo 'line 4' > readme git commit -a -m 'commit add line 4' #撤销最后一次提交,生成新的提交 git revert HEAD └─$ git log commit 1abde1cd208d9e9531efb69228ea2820421d52ad (HEAD -> master) Author: my <[email protected]> Date: Fri Sep 26 17:58:04 2025 +0800 Revert "commit add line 4" This reverts commit 4999fac66d5ba6090ed5db471be66cfdf1c6a64e. commit 4999fac66d5ba6090ed5db471be66cfdf1c6a64e Author: my <[email protected]> Date: Fri Sep 26 17:56:20 2025 +0800 commit add line 4 └─$ git reflog 1abde1c (HEAD -> master) HEAD@{0}: revert: Revert "commit add line 4" 4999fac HEAD@{1}: commit: commit add line 4 1e2131d HEAD@{2}: reset: moving to 1e2131d 946c993 HEAD@{3}: reset: moving to 946c9936f 1e2131d HEAD@{4}: commit: commit add app.py 7845649 HEAD@{5}: reset: moving to HEAD 7845649 HEAD@{6}: reset: moving to HEAD 7845649 HEAD@{7}: commit (amend): 2 append 2.1 767e203 HEAD@{8}: commit: add gitignore 946c993 HEAD@{9}: commit: Second Commit cf4ad40 HEAD@{10}: commit (initial): create file
- revert主要用在主分支上,虽然撤销了提交的修改,但log中保留了信息。在工作分支上,可以采用reset。
- revert只是撤销了指定commit的修改,会继续保留其他的修改,会在当前分支后生成一个新的commit。
- reset会把回到的commit之后的commit删掉了。
移动和删除
git mv src dest
改名,直接把改名的改动放入暂存区git rm file
会同时在版本库和工作目录中删除文件,真删除git rm --cached file
将文件从暂存转成未暂存,从版本库中删除,但不删除工作目录的该文件,即文件恢复成不追踪的状态
以上都算是改动,必须commit才算真改动
echo "test" > test.py git add test.py git commit -m "mv and delete" # 改名 git mv test.py t.py └─$ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) renamed: test.py -> t.py git commit -m "mv test.py -> t.py" └─$ ll total 16 -rw-rw-r-- 1 jasper jasper 21 Sep 26 17:53 app.py -rw-rw-r-- 1 jasper jasper 80 Sep 26 17:44 index.html -rw-rw-r-- 1 jasper jasper 16 Sep 26 17:58 readme -rw-rw-r-- 1 jasper jasper 5 Sep 26 18:06 t.py # 删除 git rm └─$ git rm t.py rm 't.py' └─$ ll total 12 -rw-rw-r-- 1 jasper jasper 21 Sep 26 17:53 app.py -rw-rw-r-- 1 jasper jasper 80 Sep 26 17:44 index.html -rw-rw-r-- 1 jasper jasper 16 Sep 26 17:58 readme └─$ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) deleted: t.py └─$ git commit -m "del t.py" [master a9489b6] del t.py 1 file changed, 1 deletion(-) delete mode 100644 t.py
push到服务器
本地搭建了一个github私服,模拟GitHub http://192.168.112.135:3000/my/test.git
- 关联远程版本库
git remote
列出所有远程仓库
git remote -v
详细列出所有远程仓库
git remote add [shortname] [url]
指定一个名称指向远程仓库
$ git remote add origin http://[email protected]:3000/my/test.git $ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = http://[email protected]:3000/my/test.git fetch = +refs/heads/*:refs/remotes/origin/*
远程版本库名origin,这是个习惯用法,将建立origin和后面url的映射,这些信息保存在.git/config文件的新的段[remote“origin”] 中
注意: http://[email protected]:3000/my/test.git 加上用户名,否则push会报401
git config --system
在/etc/gitconfig 文件中读写配置git config --global
在 ~/.gitconfig 文件中读写配置.git/config
这个文件是 版本库级别 设置文件,这里的设置具有最高优先级
推送数据
$ git push -u origin master Password: Counting objects: 7, done. Delta compression using up to 2 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (7/7), 583 bytes, done. Total 7 (delta 0), reused 0 (delta 0) To http://[email protected]:3000/my/test.git * [new branch] master -> master * Branch master set up to track remote branch master from origin. AI生成项目python运行12345678910
输入密码就可以连接到远程仓库了。
私有的仓库,必须登录,只能用户自己看,为了方便,修改为公有的。
git push <远程主机名> <本地分支名>:<远程分支名>
$ git push origin master # 指定推送到的远程主机和分支 $ git push origin # 指定当前分支推送到的主机和对应分支 $ git push -u origin master # 指定远程默认主机和分支 $ git push # simple方式,默认只推送当前分支到默认关联的远程仓库
- -u 第一次远程推送的时候加上,以后就可以不使用-u参数,可以git push origin master,也可以git push都使用默认。
echo "welcome about" > about.htm git commit -a -m "修改了about.htm" git push origin master # 或者git push
从远程库克隆
- 这一次使用git协议连接远程库。
- 为了演示跨平台,这里使用windows系统。
- 建议使用Git的windows客户端的
git bash
,它含有常用ssh命令 - 配置本地用户名、邮箱
$ git config --global user.name "jack" $ git config --global user.email "[email protected]" $ cat ~/.gitconfig [user] name = jack email = [email protected]
- 删除windows当前用户=.ssh=文件夹
$ ssh-keygen -t rsa -C "[email protected]"
- -t 加密算法类型
- -C comment 描述信息
$ ssh-keygen -t rsa -C "[email protected]" Generating public/private rsa key pair. Enter file in which to save the key (/c/Users/Administrator/.ssh/id_rsa): # 直接回车 Enter passphrase (empty for no passphrase): # 直接回车 Enter same passphrase again: # 直接回车 Your identification has been saved in /c/Users/Administrator/.ssh/id_rsa. # 私钥 Your public key has been saved in /c/Users/Administrator/.ssh/id_rsa.pub. # 公钥 The key fingerprint is: SHA256:ZxALWxgiq1UUw6TpS+p/hBeTeYOmAbIRVQNUZZ0fUxs [email protected] The key's randomart image is: +---[RSA 2048]----+ 0 |.+=B@o=+o. .E | |o. *.=.+ooo o | |.o* = o. o. | |.+ . B o .. | |. o = + S o | | o + o o | |. . o | |. . | | .... | +----[SHA256]-----+ $ cd $ ls .ssh id_rsa id_rsa.pub $ pwd /c/Users/Administrator
- 打开gogs的用户设置 -> ssh密钥
- 打开公钥文件
-/.ssh/id_rsa.pub
,将内容贴入“密钥内容”框中,点击“增加密钥”,密钥名称自己填写 - 那么SSH登录的用户使用的链接如下图
- SSH链接远程库
在windows上找一个空目录,执行下面的克隆命令
注意,第一次使用ssh连接有提示,敲入yes
$ git clone [email protected]:my/test.git Cloning into 'test'... remote: Counting objects: 28, done. remote: Compressing objects: 100% (20/20), done. remote: Total 28 (delta 0), reused 0 (delta 0) Receiving objects: 100% (28/28), done.
克隆成功
下面就可以使用这个初始的项目文件开发了
Git项目开发和多人协作
Pycharm中使用git
创建远程版本库
git私服创建cmdb项目版本库
- 提前添加密钥到git私服
- 获得远程仓库地址,如 [email protected]:my/cmdb.git
- 克隆代码到本地
- 打开IDE工具Pycharm
- 从版本控制工具中获取项目,选择Git
- 菜单中选择Project from Version Control–>Git
- 选择项目目录,填入远程版本库地址
- Clone成功,并直接用Pycharm打开项目。
- 从版本控制工具中获取项目,选择Git
- 打开IDE工具Pycharm
#查看远程信息 jasper@jasper MINGW64 /d/project/PythonProject/cmdb (master) $ git remote origin jasper@jasper MINGW64 /d/project/PythonProject/cmdb (master) $ git remote -v origin [email protected]:my/cmdb.git (fetch) origin [email protected]:my/cmdb.git (push)
项目开发
- 添加app.py文件
- 提示是否加入到git
编写源码 app.py
if __name__ = "__main__": print("helle world")
第一次提交
- Git–>Commit
- 这里可以选择提交,或提交并推送。本次选择提交。 并写上提交信息。
Pycharm中查看版本信息
- 菜单栏–>View–>Tool Window –>Git(Altr+9)
这只是放入到本地仓库。
推送
- Git–>Push
- 成功push。私服查看
分支branch
多人协作一起开发,开发项目中不同的独立的功能,这些功能可能需要好几天才能完成。又或者为客户定制软件,往往需要一个不同的定制需要。这往往需要在代码上开辟不同的分支。
代码中至少有一个分支,就是主干分支或者称主分支master,默认都是在主分支上开发。
分支名
分支名
- 分支名在版本库中必须唯一
- 不能以 - 开头
- 可以使用 /,但是不能以它结尾,被它分割的名称不能以.开头
- 不能使用两个连续的 ..
- 不能包含任何空白字符、Git的特殊符号
注: 分支名一般要么叫 Master 要么叫 dev
单分支
master .---> . ---> . #点表示每一次提交commit
项目往往是并行多人开发的,都在主分支上克隆,然后修改提交,那么主分支就会有存在大量的冲突。甚至有一些 不完善代码提交,主分支就混乱不堪,不可维护了。
再一个,如果一次提交后,需要发布一个版本,这个版本以后需要独立维护、开发,而主分支还需要继续发展,怎 么办?例如3.5版本发布后,增加了新功能3.6,然后3.5版本还需要修改bug。
需要使用多分支。
多分支
创建分支
需要指明从什么分支上创建什么名字的分支。
可以在版本控制的Log标签页查看(Pycharm Alt+9)。
- New branch –> dev
成功创建分支。相当于 git checkout -b dev
创建一个工具模块,并提供一个封装函数。
# utils/__init__.py from urllib import request class Request(request.Request): def __init__(self, url): super().__init__(url) self.add_header( 'User-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36' ) def get(self): """返回结果""" return request.urlopen(self)
Git –> Push commit 并抢着到远程仓库。
协作开发
打开Linux桌面系统。
git config --global user.name 'ubuntu' git config --global user.email '[email protected]' └─# cat ~/.gitconfig [user] name = ubuntu email = [email protected] # ssh 密钥 ssh-keygen -t rsa -C '[email protected]' cat .ssh/id_rsa.pub
同样操作,clone项目,然后checkout到dev分支
git clone [email protected]:my/cmdb.git cd cmdb git checkout dev mkdir monitor └─# vim monitor/__init__.py from utils import Request def ip_check(url): #'http://myip.ipip.net' request = Request(url) pass
存储stash
命令 | 说明 |
---|---|
git stash | 暂时存储最后一次提交后的变化,放入栈中 |
git stash pop | 从栈中取出刚才保存的变化,并合并 |
ubuntu正在开发过程中,突然领导说app.py中有一个紧急修改bug,需要马上修复。可是现在代码没有写完,不想提交。
git add monitor/ └─# git stash Saved working directory and index state WIP on dev: 60d43e5 2 增加utils和Request封装类 └─# ll total 8 -rw-r--r-- 1 root root 52 Sep 27 14:34 app.py drwxr-xr-x 2 root root 4096 Sep 27 14:38 utils
这时候发现app.py急需完善代码,但是分发器模块块没有完成不想提交,这时候就需要stash了。
如果是Pycharm, Git–>Stash Changes–>Create Stash
执行完,工作区回到了上次提交的样子,回到app.py中完成修改,最后提交。
└─# vim app.py if __name__ == '__main__': print('hello world!!!!') #提交并推送 git add app.py git commit -m 'fix app.py' git push
现在可以unstash并pop 刚才保存的代码,并开发。
└─# git stash list stash@{0}: WIP on dev: 60d43e5 2 增加utils和Request封装类 └─# git stash show monitor/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) └─# git stash pop On branch dev Your branch is up to date with 'origin/dev'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: monitor/__init__.py Dropped refs/stash@{0} (69e3b225c153c487509a24c23ed909ca36561cdb) └─# ll total 12 -rw-r--r-- 1 root root 57 Sep 27 14:49 app.py drwxr-xr-x 2 root root 4096 Sep 27 14:54 monitor drwxr-xr-x 2 root root 4096 Sep 27 14:38 utils
如果是Pycharm, Git–>UnStash Changes
- Stashes
- Pop Stash –> Pop Stash
monitor/__init__.py文件又变成了刚才修改过的样子,继续完成代码,提交。
└─# vim monitor/__init__.py from utils import Request def ip_check(): request = Request('http://myip.ipip.net') with request.get_text() as response: print(response) └─# git add monitor/ └─# git commit -m 'add monitor/__init__.py' └─# git push
应用场景
- 开发中,当前手中的工作没有完成,需要 中断 当前工作来完成其他请求,例如修复Bug。
- 已完成的工作内容提交不合适,可能还要需要大的调整,但是紧急请求又不能不做,就需要stash存储未完成的工作(上次提交后做的修改)。
分支branch
注:以下的操作都在Pycharm中完成,其它IDE都可以实现类似的功能
- 多人协作一起开发,开发项目中不同的独立的功能,这些功能可能需要好几天才能完成, 又或者定制版本,往往需要一个不同的定制需求。
- 代码中至少有一个分支,就是主干分支或称主分支Master,默认都是在主分支上开发。
Pull
如果要对某个分支代码进行开发,应该先对该分支进行pull操作,以拿回新代码。
如windows下用户开始pull dev代码。
if __name__ == '__main__': print('hello world') print('=' * 30) $ git status On branch dev Your branch is up to date with 'origin/dev'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: app.py
git pull origin dev
发现冲突
15:14:03.612: [cmdb] git -c credential.helper= -c core.quotepath=false -c log.showSignature=false pull --no-stat -v --progress origin dev remote: Total 12 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0) From 10.0.0.152:my/cmdb * branch dev -> FETCH_HEAD 60d43e5..21c6a1e dev -> origin/dev error: Your local changes to the following files would be overwritten by merge: app.py Please commit your changes or stash them before you merge. Aborting
冲突解决
由于某种原因,ubuntu对app.py进行了修改并push了代码。
之后windows用户并没有pull操作,直接对app.py进行了修改。
测试成功。先commit.
然后再PUSH代码。
有冲突产生,需要后提交者解决冲突,点击Merge.
合并代码后,点击Apply. 然后PUSH到远程仓库
合并merge
dev开发告一段落,需要将功能合并入master。 切换回到master,检出master
git checkout master git merge --no-ff dev
开始合并,选择No Fast Forword合并
CVS–>Git–>MergeChanges
- dev No fast forward
- Merge
目前的合并,只是本地,需要push到远程库
当然还可以继续检出dev分支,继续开发,开发好了,合并进来
Fast Forward 合并

从前面操作的图中可以看到,默认NoFF不勾选,也就是默认使用FF方式合并。
no-ff的好处是,可以看清楚开发分支上的代码改动。
上面dev分支总是开发中的代码,dev测试、审查后合并到master中。
master分支都是稳定的代码,可以发布部署。
Tag
git tag <标签名> #打标签 git tag -l #查看 git push --progress --porcelain origin refs/heads/master:master --follow-tags
- Git–>New Tag
- Git–>Push 勾选Push Tags Curren Branch
GitFlow工作流
不同公司,不同的项目规模,不同的管理水平都有着不同Git工作流方式。
最佳实践
- 使用Git一般至少2个分支:master和develop
- master,主干,生产环境都来主干分支上拿数据部署,也可以使用钩子自动完成
- develop,开发分支,开发人员都是检出这个分支开发
- 辅助分支
- feature 分支,具体的功能开发分支,只与 develop 分支交互。
- release 分支,发布版本
- hotfix 分支,紧急bug修复的版本,最后需要合并到develop 和 master中。
