【DevOps】git + gitee + flask + webhooks完成 代码管理 与 服务器自动化同步

理想方案


代码在家里和公司的机器上,在所有的服务器上,均实现同步功能

git基础


关于git

git是一个开源分布式的版本控制系统;

概念

工作区:存放代码的目录;

暂存区:又叫 stage 或 index,是一个名为 index 的文件,在 .git 目录下;

Git 仓库目录:是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。

分支:解决开发版本和线上稳定版本的冲突问题;默认只有master分支,新加功能时,一般创建一个新的分支,修改后再合并到master分支;

三种状态

已修改(modified):工作区有文件已修改,但未添加到暂存区;

已暂存(staged):已修改的文件已经添加到暂存区,执行 commit 时可以提交到本地分支;

已提交(commited):已把暂存区的修改提交到本地分支;

流程

新建git仓库 > 工作区 增删改 文件 > 添加到暂存区 > 提交到 git 仓库目录 > 同步到远程仓库;

git init > 编辑 > git add . > git commit -m “msg” > git remote add origin ssh地址 > git push origin master

常用命令

  • git init

    对现有的某个项目开始用 Git 管理 ,需要进入该项目所在目录,执行 git init即可;

    执行后,在该目录下会看到一个隐藏文件夹 .git ,其中包括 暂存区(index文件),master分支,和指向 master 的head指针;

    git init
    
    git init path
    
  • git config

    git config --list
    git config  --global  user.name "[name]"
    git config  --global  user.email "[email address]"
    
  • git add

    将文件添加到暂存区,建议每次工作区发生变化后都执行一次;

    git add file1 file2 file3
    git add .
    git add -A
    
  • git commit

    提交到本地分支

    git commit -m
    git commit -a
    # 提交时显示 diff 信息
    git commit -v
    
  • git remote

    # 本地关联一个新的远程仓库,并命名远程仓库 为 origin 
    git remote add origin [url]
    
    # 查看已经关联的远程仓库
    git remote -v
    git remote
    
    # 删除已经关联的某个远程仓库
    git remote remove origin
    
  • git push

    上传本地分支 branch_name 到远程仓库 origin

    git push -u origin branch_name
    # 强行覆盖远程分支
    git push origin branch_name -f
    # 推送所有分支
    git push origin -a
    
  • git clone

    本地不需要 git init,直接从远程把仓库的所有内容都 克隆到本地,包括 .git 文件;

    git clone [url]
    
  • git pull

    取到远程仓库的变化,并与本地分支合并,相当于 git fetch + git merge

    git pull origin branch_name
    
    # 将 merge 改为 rebase,相当于覆盖
    git pull origin branch_name --rebase
    
    # 强行pull覆盖本地,不合并(放弃本地修改)
    git fetch --all
    git reset --hard origin/master
    git pull //可以省略
    
  • git diff

    查看发生的变化

    git diff # 查看工作区发生的变化
    
    git diff -s # 查看暂存区发生的变化
    
  • git rm

    # 删除工作区文件,并提交到暂存区
    git rm file1 file2
    git rm -R path
    # 停止跟踪某文件 或 路径 ,但不从工作区删除
    git rm --cached file1 file2
    
  • git log

    查看提交历史

    git log
    git log --stat	# 查看详细提交记录
    
  • git remote -v

    显示所有远程仓库

  • git branch

    # 列出本地分支
    git branch
    
    # 列出远程分支
    git branch -r
    
    # 列出 所有分支(本地 + 远程)
    git branch -a
    
    # 新建分支
    git branch branch_name
    
    # 切换分支
    git checkout branch_name
    
    # 新建分支并切换过去
    git checkout -b branch_name
    
    # 合并分支到当前分支
    git merge branch_name
    
    # 删除分支
    git branch -d branch_name
    
    # 删除远程分支
    git push origin --delete  branch_name
    git branch -dr remote_brach
    
  • git status

    git status 可以查看 哪些文件 处于什么状态,有如下几种情况:

    1、Changes to be committed:说明工作区的文件已添加到暂存区,但是还未提交到 git 仓库;

    2、Your branch is up-to-date with ‘origin/master’.nothing to commit, working directory clean:显示你的本地分支 对应的 远程 分支,没有要提交到git仓库的,工作区很干净(指没有增删改)

    3、Changes not staged for commit: modified test.txt:有改动未提交到暂存区;

    4、Untracked files: filename ,nothing added to commit but untracked files present:新增了文件,未提交到暂存区,未跟踪的文件;

删除文件

1、从工作区移除,并从暂存区移除;

git rm filename
git rm path
git rm log/\*.log

2、从暂存区移除,但工作区保留

git rm --cached filename

重命名文件

以下命令相当于 mv oldname newname > git rm oldname > git add newname

git mv oldname newname

清空本地仓库

git branch

git checkout -b  master2 (git branch master2 和 git checkout master2 的合并)

gid add.

git commit -m "msg"

git branch -D master

git branch -m master

git push -f origin master 

使用 ignore 忽略不想跟踪的 文件 或 文件夹

可以在项目根目录(即 执行 git 命令的目录)创建 .gitignore 文件,举例;

附上 各个语言的 参考 .gitignore文件 :https://github.com/github/gitignore

# 忽略所有的 .a 文件
*.a

# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a

# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO

# 忽略任何目录下名为 build 的文件夹
build/

# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt

# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf

我目前使用的 gitignore:

*.log # 忽略服务器运行程序产生的log文件
Temp/ # 忽略本地开发时使用的temp文件夹
.idea/ # 忽略pycharm产生的缓存文件

适合 python 的 gitignore:

参考:https://github.com/github/gitignore/blob/master/Python.gitignore

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

Tips

1、git 提交时 出现 ”warning: LF will be replaced by CRLF“

Linux 的换行符是 LF (换行),Windows 的是 CRLF(回车CR+换行LF);

Linux 上 : git config --global core.autocrlf input

Windows上:git config --global core.autocrlf true (默认就是这样)

git 学习资料

git 简易指南(适合快速学习):https://www.bootcss.com/p/git-guide/

git 资源大全:https://gitee.com/all-about-git

https://git-scm.com/book/zh/v2

https://www.liaoxuefeng.com/wiki/896043488029600

https://www.runoob.com/git/git-tutorial.html

https://gitee.com/help/collected_article

https://blog.csdn.net/u013374164/article/details/78831480

书籍 ProGit 中文版:https://gitee.com/progit/

使用Git 完成 家里、公司服务器 代码同步


场景一 :本地代码通过git提交到gitee

1、下载与安装git

https://npm.taobao.org/mirrors/git-for-windows/,下载 Git-2.27.0-64-bit.exe ,并安装;

2、配置个人信息

git config --global user.name "Ezrealer"

git config --global user.email [email protected]

git config --list

3、 创建项目目录 E:\GitCodes\ ,放入代码 E:\GitCodes\MyProgram

4、在 E:\GitCodes\MyProgram 下 创建 .gitignore 文件,描述 不跟踪的文件或文件夹;

# .gitignore 文件内容

*.log # 忽略服务器运行程序产生的log文件
Temp/ # 忽略本地开发时使用的temp文件夹
.idea/ # 忽略pycharm产生的缓存文件
.idea

5、在路径 E:\GitCodes\CopyrightMonitor 下 ,执行 git init 创建仓库,在路径下生成 .git 文件夹,其中包括 暂存区(index文件),master分支,和指向 master 的head指针;

6、使用 git add . 和 git commit -m “msg” 添加 当前工作区 到 暂存区 ,并提交到当前分支;

注意(都有解决办法):

  • git是无法add空文件夹的,需要保留项目结构的话,需要在空文件夹创建个文件占位,官方推荐创建一个 .gitkeep 文件;

  • 不能存在 大于 100M 的文件,否则 push不到远程服务器;

(windows 上 使用 commit -am “msg” ,失败了,不知道原因暂时)

git add a .

git commit -m "MyProject @ 20200616"

7、如果是本机 第一次使用git ,则需要在本地创建 公钥,并添加到远程仓库;

ssh-keygen -t rsa -C "[email protected]"

enter > enter > enter

# Your identification has been saved in C:\Users\Ezreal/.ssh/id_rsa.
# Your public key has been saved in C:\Users\Ezreal/.ssh/id_rsa.pub.

打开 C:\Users\Ezreal/.ssh/ 文件夹下的 id_rsa.pub 文件,复制生成的公钥;

打开 gitee 的 个人主页 > 个人设置 > 安全设置 > SSH公钥 > 把复制的公钥粘贴在提示的地方 > 生成公钥;

8、在 gitee 上 创建仓库,仓库名为 MyProgram ,保持仓库为空,不勾选 .gitignore 文件 和 README 文件,防止 第一次 push 出错,然后 在 仓库主页的 克隆/下载 中复制ssh地址;

9、将本地分支关联到远程仓库,并为远程仓库起名 origin;

git remote add origin  [email protected]:Ezrealer/MyProgram.git

git remote -v

10、推送当前分支到gitee仓库;

git push -u origin master

# 强行 用 本地的代码 覆盖 gitee 上的
git push -u origin master -f

11、如果 执行 git commit 后,想在工作区删除某个文件或文件夹,则可以

# 清除本地git仓库缓存
git rm -r --cache .

git add.
git commit -m "msg"

场景二:从gitee上把代码拉到服务器

1、安装 Git,服务器一般是Linux 系统,基本会自带 git ,可以通过 git --verison 查看;

2、如果服务器是第一次使用git,则需要 生成公钥,并添加到 gitee 的 ssh 公钥中;

ssh-keygen -t rsa -C “xxx.xx.17.174"
enter > enter > enter

# Your identification has been saved in /home/Ezrealer/.ssh/id_rsa.
# Your public key has been saved in /home/Ezrealer/.ssh/id_rsa.pub.

cat /home/Ezrealer/.ssh/id_rsa.pub
# 复制 生成的 ssh key

复制 生成的 ssh key > 打开 gitee 的 个人主页 > 个人设置 > 安全设置 > SSH公钥 > 把复制的公钥粘贴在提示的地方 > 生成公钥;

3、创建一个文件夹,作为放代码的地方

cd /usr
sudo mkdir GitCodes
sudo chmod -R 777 GitCodes
cd GitCodes

4、克隆 gitee 的代码 到 本地;

git clone [email protected]:Ezrealer/MyProgram.git

git clone 命令 执行的 操作:

  • git init(创建本地存储库)
  • git remote add(将URL添加到该存储库)
  • git fetch(从该URL中获取所有分支到本地存储库)
  • git checkout(创建工作树中主分支的所有文件)

5、修改本地代码,再次上传到远程gitee仓库;

git add.
git commit -m "msg"
git remote add origin [email protected]:Ezrealer/CopyrightMonitor.git
git push -u origin master

场景三:家里的电脑 同步 工作后的修改;

工作了一天,把工作后的修改已经提交到gitee上,此时家里的代码还是昨天晚上的,需要把今天的修改同步过来;

git pull 拉取修改,此时相当于执行了 git fetch + git merge;

git pull origin master

编写python脚本完成项目的 push 与 pull;

1、安装 gitpython 模块

pip install gitpython

2、push

在项目根目录下创建 gitee_push.py

from git import Repo
import datetime

repo = Repo("./") #git文件的路径
git = repo.git

print("当前未跟踪文件:",repo.untracked_files)
print("当前本地git仓库状态:",git.status())
print("当前本地git仓库是否有文件更新:",repo.is_dirty())
print("当前本地分支:",git.branch())
print("当前远程仓库:",git.remote())

print("正在 git add .")
git.add('.')
commit_msg  = "By gitpython @ {0}".format(str(datetime.datetime.now())[:19])
print("正在 commmit -m {0}".format(commit_msg))
remote_name = "origin"
print("正在推送到远程仓库: {0}...".format(remote_name))
git.commit('-m', commit_msg)
git.push(remote_name)
print("推送到远程仓库 {0} 成功!".format(remote_name))

3、pull

在项目根目录下创建 gitee_pull.py

from git import Repo
# 推送
repo =Repo("/usr/GitCodes/CopyrightMonitor") #git文件的路径
git = repo.git

print("当前未跟踪文件:",repo.untracked_files)
print("当前本地git仓库状态:",git.status())
print("当前本地git仓库是否有文件更新:",repo.is_dirty())
print("当前本地分支:",git.branch())
print("当前远程仓库:",git.remote())

remote_name = "origin"
print("正在 git pull {0} master".format(remote_name))
git.pull(remote_name,"master")
print("拉取修改 {0} 成功!".format(remote_name))

Flask 实现 WebHooks 方式 自动 同步 gitee 代码到 服务器


Flask

WebHooks

实现

1、安装

pip install flask

2、服务器需要将自己的ssh 公钥 添加到 gitee,且需要 将 本地仓库关联到 gitee的仓库

git remote add origin [email protected]:Ezrealer/Myprogram.git

如果服务器之前没跑过此项目,则需要先 克隆 gitee 上的项目到本地;

cd /usr/GitCodes
git clone [email protected]:Ezrealer/CopyrightMonitor.git

3、gitee > Myprogram仓库主页 > 管理 > WebHooks > 配置 IP和密码 > 选择事件(暂时只选push)

IP为 http://服务器IP:端口/gitee/webhook,密码自己设定,可以在获取 post 的请求数据时 得到,用于验证请求合法性;

4、脚本

在项目根目录新建文件 webhook_server.py ;

from flask import Flask,request
import json
from git import Repo
import datetime

app = Flask(__name__)


def gitee_pull():

    repo = Repo("/usr/GitCodes/CopyrightMonitor")  # git文件的路径
    git = repo.git

    print("当前未跟踪文件:", repo.untracked_files)
    print("当前本地git仓库状态:", git.status())
    print("当前本地git仓库是否有文件更新:", repo.is_dirty())
    print("当前本地分支:", git.branch())
    print("当前远程仓库:", git.remote())

    remote_name = "origin"
    print("正在 git pull {0} master".format(remote_name))
    git.pull(remote_name)
    print("拉取修改 {0} 成功!".format(remote_name))

@app.route('/gitee/webhook',methods=["POST"])
def get_tasks():
    if request.method=='POST':
        # password=request.form['password']
        # print(password)
        #print(request.headers)
        #print(request.form)
        #print(request.args)
        print("请求地址:",request.url)
        print("=" * 50)
        print("请求方法:",request.method)
        print("=" * 50)
        print("请求内容:")
        request_dict = json.loads(str(request.data, encoding = "utf-8"))
        print(request_dict)
        print(type(request_dict))
        print("=" * 50)
        if request_dict.get("password") == "xxx":
            print("密码验证通过,开始拉取...")
            gitee_pull()
            print("拉取成功!",str(datetime.datetime.now())[:19])
            return "success"
        else:
            print("密码验证失败...",request_dict.get("password"))
            return "password is error"

app.run(host="0.0.0.0", port=8000, debug=False)

运行流程

1、远程服务器启动项目根目录下的 webhook_server.py

2、在本地的ide里启动项目根目录下的 gitee_push.py

3、查看gitee上是否同步成功

4、查看服务器是否同步成功

5、注意,不可在服务器上直接修改代码,不然pull的时候就会报错,需要merge纠正;

你可能感兴趣的:(【DevOps】)