RENZHAI版本Git小程序
文档 下载 评论(0)

 

 

 

哈喽 大叫好,我叫人宅 很高兴和大家分享一下 我自己写的git小程序。

这个是人宅版本的git 实例 ,我把它放在了OSS服务器上 (如果对OSS服务器感兴趣的小伙伴可以点击 阿里云OSS服务器课程)

解压打开git 可以看到如下文件

这个程序比较小众,估计也没多少人看~_~

不管怎么样 还是要解释一下如何测试这个程序,因为这个renzhai版本的git版本控制还有很多可以学习的内容。

1.install.bat :安装的意思是模仿git 的安装点击后会自动安在菜单上,如下:

2.uninstall.bat 直接可以从菜单上移除掉。

3.这里我建立了三个文件

client1    //用户2
client2   //用户1
server   //git 服务器存储的位置

4.先启动服务器,服务器的启动非常简单,只需要将图中的gitrenzhai_server.exe拷贝到你的server文件里面 作为仓库;

5.双击运行,服务器就算是启动了,非常简单。

6.启动后会自动生成以下文件:

其中:

.git //里面存储着git相关信息,比如用户提交信息,用户各个版本信息,用户具体版本等,我们稍后会分析
git_server //
log //服务器本地日志
README.txt //基础操作

打开.git

其中有以下信息

  • version \\这里面存放着各个上传版本的具体内容
  • DO8D1043….CD…. \\这个是上传具体版本里面的文件列表
第一个是上传的类型 是覆盖还是删除还是添加
第二个是filename
第三个是crc 校验码
第四个是文件大小 以字节为单位
  • file_list.file //当前文件的文件列表
  • ignorepath.ig //忽略的路径
  • igore_suffix.ig //忽略的后缀
  • version.list //各个版本的列表

服务器启动完毕后就可以启动客户端

7.先进入client1

8.鼠标右键启动客户端

9.我们现在启动了一个客户端,通过git init 命令初始化一个仓库:

此时客户端会生成如下内容:

.git //记录着客户端本地信息
git_client //
log //客户端本地日志

10.打开客户端.git

里面生成了三个文件

git.txt //为git 进行git定位
ignore_path.ig // 本地忽略的路径,防止上传不合法的内容
ignore_suffix.ig //忽略的文件的后缀

11.我们可以通过git –help的命令了解更多命令

12 我们可以通过git –global user.name 来注册一个用户的名称这里以人宅为例子:

13 我们可以通过git –global user.email 来注册一个用户的邮箱:

14 然后就是拉去服务器的数据版本,这里我推荐两种方法,这两种方法都可以实现拉取~

方法一:

git remote add origin 【 URL】 // 这里的URL是服务器的路径 URL = M:\Server
git pull // 拉版本

方法二

git clone【 URL】 // 这里的URL是服务器的路径 URL = M:\Server

当我们进行更新后 我们可以看到客户端文件的变化:

成功的拉取了服务的README.txt,并且在.git里面多了如下的内容:

git_user.ini 里面存储着当前客户端账户信息:

version.info 里面存储着当前最新版本提交的信息:

里面存储着当前最新版本列表 因为我们只拉去了服务器的一条数据 README.txt,如果有多条,这里面将显示多条数据:

现在 我们在客户端放置一个测试文件 这个文件是SimpleThread UE4插件的源码:

15我们需要将数据发送到服务的,作为一个新的版本,其他用户会更新你上传的这个版本。你可以通过git add Source 和 git add . 这两种命令进行添加:

方法一:

方法二:

git add [文件名称] //添加文件下所以子文件的子文件
git add .// 添加当前目录下的所有文件

16 添加好后我们可以通过git commit -m “你提交的内容” 描述你提交此次版本的内容;

这一步很关键,如果没有这一步 后面的提交将是失败的。

17 最后我们通过git push 将数据发送到远端的服务器;

你也可以通过git push -u origin master 这个命令来完成推送,当前的小程序暂时不考虑分支方面的操作;

现在我们来看看服务的,是不是多了一个Source ?我们已经完成了一个文件的推送;

18 我们可以通过git status 来查看客户端当前版本文件的变动情况:

19 测试一下 删除和更新 观察服务的变化,这里我删除该文件内的Coroutnes和Runnable 并且将ThreadManage.h的大小进行改变:

我们现在对Source里面的内容进行提交 查看变化情况;

我们现在已经对服务器上的数据进行了修改。从表中我们可以看到我们已经移除了服务器指定的数据,并且我们的git也成功的检测出文件的变化,只更新有变化的文件;

现在,我们通过git status 来查看当前版本的文件变化:

这个小程序 我做了特殊处理,覆盖用灰色,红色代表移除 蓝色代表添加

我们先看看版本提交的情况,我们可以通过git log来查看 历史提交情况;

我一共提交了两次,可以清晰的看到提交人和提交信息 以及提交的日期;第一个提交是服务器提交的,这个是默认提交内容,只要开启服务器 会自动生成一个。

现在,我们按照这种方法试一下另外一个客户端,看看它们是否可以协调工作。

打开客户端2,我们能清楚的看到这个客户端:

先git init 初始化一个仓库;
再通过 git --global user.name 注册一个名字 
最后用git clone 拉取服务端的数据内容。

client2已经成功的将数据从服务器拉去到了

我们现在有两个客户端 一个是人宅 一个是小白;

正常操作中 我们需要这两个客户端不停提交版本,更新版本,方便工作中相互协作,相互合作,那么我们来测试一下迭代更新。

现在小白完成了他的模块 需要提交文件,我们来看看他的操作;

20 我们复制了一份 public 并且 把 Private整体删除;

最后我们进行提交;

21 因为数据太多,我们可以通过git status 来查看上传版本的文件具体行为。

可以看到我们删除了Private 上传了 Public – 副本;

可以看看我们的服务端情况:

和客户端2的结构吻合。

现在我们来到客户端1(人宅) 进行更新。

客户端本地数据信息:

22.最后 我们还剩下一个冲突的测试 如果客户端一提交了版本数据 ,而客户端2修改了本地文件,这个时候客户端2进行更新,更新的文件刚好是客户端1提交的内容,这样就报错了,这个就是一个冲突,我们的git经常有这方面的错误提示,现在我们来测试一下:

还是原来的文件,我们对SimpleThread.build.cs这个文件做一些操作,把它变大;

3 KB – 11KB

现在我们来提交 客户端1的内容:

提交的信息如下:

我们现在对客户端2内容进行修改 :

我们现在更新客户端2

显示我们的客户端2其中SimpleThread.build.cs发生了错误,本地和服务端产生冲突 需要解决。

解决方法很简单 备份本地数据 重新拉去服务器最新数据 ,将修改的数据复制到服务器最新版本,提交即可,这个是git传统的操作方案。git并不像SVN那样可以进行代码行的合并。

现在我们来删除这个文件,这样,就可以获取服务器更新的数据,冲突也就解决了。

拉取版本:

解决了冲突:

我们来查看一下提交信息;

具体提交的状态:


现在我们把问题搞的复杂一些 来全面测试该程序

现在我们对客户端1 的SimpleThreadPlatform.h和ThreadManage.h进行删除 并且修改了文件SimpleThread.h

整个文件修改后变成了这样~

现在我们提交一下客户端1

现在我们再添加再删除,准备一个版本;

再上传

最后我们移除这些文件

客户端1再上传

人宅客户端1上传了 好几个版本,现在我们来看看客户端2小白的更新情况。因为实际项目中比这个更复杂,这种测试是必要的。

大家应该按照操作,可以看到相应的结果,感谢抽时间看到这么远;

服务器源码.h:

#pragma once
//Copyright (C) RenZhai.2019.All Rights Reserved.
//作者 人宅
//该c库的详细源码讲解在AboutCG 《手把手入门硬核c语言》视频工程里面:
//https://www.aboutcg.org/courseDetails/902/introduce
//希望学习其他方面技术 比如做UE4游戏, 可以访问下列网址:
//https://zhuanlan.zhihu.com/p/60117613
//
//bibi可以看到各个人宅系列教程介绍:
//https://space.bilibili.com/29544409
//
//个人博客网站
////renzhai.net
//
//关于本套案例的详细操作 :
//文字版本(详细):
//https://zhuanlan.zhihu.com/p/144558934
//视频版本:
//https://www.bilibili.com/video/BV1x5411s7s3
#include "protocal_type.h"

char git_project_path[MAX_PATH] = { 0 };
char git_version_list_filename[MAX_PATH] = { 0 };
char git_version_filename[MAX_PATH] = { 0 };
char git_server_cache_path[MAX_PATH] = { 0 };
char git_path[MAX_PATH] = { 0 };
char git_version_path[MAX_PATH] = { 0 };
char version_tmp[MAX_PATH] = { 0 };

//具体文件在服务器的状态
typedef struct
{
	bool b_exit;
	char filename[MAX_PATH];
	simple_c_guid crc;
	unsigned int filesize;
}ffile_info;

//文件列表
typedef struct
{
	int size;
	ffile_info data[8196];
}ffile_list;
ffile_list file_list;

typedef struct
{
	int size;
	char data[MAX_PATH][1024];
}fpath;
fpath ignore_path,ignore_suffix;

//提交版本的信息
typedef struct
{
	char name[MAX_PATH];
	char commit[MAX_PATH];
	char date[MAX_PATH];
	simple_c_guid guid;
}fgit_commit;

typedef struct
{
	unsigned int size;
	fgit_commit commits[1024];
}fgit_commits;

fgit_commits commits;


//文件版本操作类型
typedef enum
{
	NONE_File,
	ADD_FILE,
	SUBTRACT_FILE,
	OVERLAP_FILE,
}eversion_operation_type;

//单个文件的版本
typedef struct
{
	eversion_operation_type operation_type;
	unsigned int file_size;
	char file_name[MAX_PATH];//
	simple_c_guid crc;
}fgit_version;

//整体文件的版本
typedef struct
{
	unsigned int size;
	fgit_version paths[2048];
	simple_c_guid crc;
}fgit_versions;

//整体文件版本列表
typedef struct
{
	unsigned int size;
	fgit_versions paths[1024];
}fgit_versions_list;
fgit_versions_list versions_list;

void init_path(fpath* p);
void string_to_path(const char* data, fpath* p);
void path_to_string(char* data, const fpath* p);

void init_commit(fgit_commit *out_commit);
void init_versions(fgit_versions *in_versions);
int get_index_by_commit(const char* client_crc, fgit_commit** out_commit);
int get_nest_index_by_commit(const char* client_crc, fgit_commit** out_commit);
const char *get_git_version_path();
const char *get_git_version_crc_path(const char *crc);
void compare_list_v(const fgit_versions* in_versions_a, const fgit_versions* in_versions_b, fgit_versions* out_versions_add, fgit_versions* out_versions_remove);
void compare_list(const fgit_versions* client_version_list, const def_c_paths* local_paths, def_c_paths* out_paths);
fgit_versions* find_versions(const simple_c_guid *crc);
fgit_versions* get_newest_versions();
void save_newest_versions(const char *crc_buf);
const fgit_commit* get_newest_commit();

char *git_commit_to_string(const fgit_commit *git_commit, char *buf);
void string_to_git_commit(fgit_commit *git_commit, const char *buf);
void string_to_git_commits(fgit_commits *git_commit, const char *buf);
void commits_to_string(const fgit_commits *git_commit, char *buf);
void string_to_ignore_path(const char *buf);
void string_to_ignore_suffix(const char *buf);

void def_c_paths_to_versions(const def_c_paths * c_paths, fgit_versions *v_version);

void versions_to_string(char *buf, const fgit_versions *in_versions);
void string_to_versions(const char *buf, fgit_versions *in_versions);
void commits_to_versions(const fgit_commits *git_commit, fgit_versions_list *in_versions);

const struct simple_c_guid *find_file_list_crc(const char *fliename);
unsigned int find_file_list_filesize(const simple_c_guid *crc);
const char* find_file_list_filename(const simple_c_guid* crc);
ffile_info* find_file_list_version_crc(const simple_c_guid* crc);
ffile_info* find_file_list_version_by_filename(const char* fliename);
int find_file_list_version_by_index(const char* fliename);
bool is_exit_filename_in_filelist_by_filename(const char* fliename);
bool is_exit_filename_in_filelist_by_crc(const simple_c_guid* crc);
void init_file_info(ffile_info* info);
void init_file_list();
void save_file_list();
void read_file_list();
void add_files_list_unique(const fgit_versions *v);
void add_file_list_unique(const fgit_version* git_version);
void remove_file_list_unique(const ffile_info* fi);
void add_file_list(const fgit_version * git_version);
void replace_file_list(int index ,const fgit_version* git_version);
void replace_file_list_s(ffile_info *info, const fgit_version* git_version);
bool add_file_list_check(const fgit_version* git_version);

//将相同版本和不同版本合并为一个具有相同和不同的版本
void compare_list_combine(const fgit_versions *in_versions_a, const fgit_versions *in_versions_b, fgit_versions *out_versions);
//寻找两个版本中 不存在的版本
void compare_list_exit(const fgit_versions *in_versions_a, const fgit_versions *in_versions_b, fgit_versions *out_versions);

const char *get_git_project_path();
const char *get_git_server_cache_path();
const char *get_git_version_filename();
const char *get_git_current_version_filename();
const char *get_git_path();
void init_server(int argc, char *argv[]);
void listening_clients();
void close_server();
bool is_exit_ignore(const char *path);

unsigned char get_protocal(); // 定义255个协议
void get_protocal_content(char *buf);

客户端源码.h

// Copyright (C) RenZhai.2019.All Rights Reserved.
/*
 下面的网址讲解了如何使用git renzhai 的版本控制
 DocURL:			https://www.bilibili.com/video/BV1x5411s7s3

 下面的网址讲解如何入门c语言 
 MarketplaceURL :  https://www.aboutcg.org/courseDetails/902/introduce

 如果想了解更多关于UE4教程请参考:
 URL :				https://zhuanlan.zhihu.com/p/60117613

 如果想系统了解人宅系列教程以及相关插件迭代更新 可以关注我的博客
 URL :				//renzhai.net/

 如果想了解我们下一节的课程安排可以 可以在微信公众号搜所 人宅 关注即可 我们会推送很多富有技术的文章

 新浪博客 https://weibo.com/BZRZ/profile?s=6cm7D0  //这个博客从16年到现在 有三四年没怎么用过 以后说不定可以重新启用 先发个连接

 */
#pragma once
#include "protocal.h"

char project_name[MAX_PATH] = { 0 };
char git_current_version_filename[MAX_PATH] = { 0 };
char git_version_filename[MAX_PATH] = { 0 };
char git_path[MAX_PATH] = { 0 };
char git_client_cache_path[MAX_PATH] = { 0 };
char git_project_remote_url[MAX_PATH] = { 0 };// 远端仓库
char git_project_path[MAX_PATH] = { 0 };//git路径 .git
char git_remote_origin[MAX_PATH] = { 0 };//远端路径 url
char git_local_cofg_filename[MAX_PATH] = { 0 };//用户配置信息
const char git_local_cofg_file[] = ".\\.git\\";//本地配置的目录
int b_exit = false;

//////////////////////////////////////////////////////////////////////////

typedef struct
{
	int size;
	char data[8196][1024];
}fpath;
fpath server_list, ignore_path, ignore_suffix;

//用户信息
typedef struct fgit_user
{
	char name[MAX_PATH];
	char password[MAX_PATH];
	char email[MAX_PATH];
};
struct fgit_user user;

//提交版本的信息
typedef struct
{
	char name[MAX_PATH];
	char commit[MAX_PATH];
	char date[MAX_PATH];
	simple_c_guid guid;
}fgit_commit;
fgit_commit commit;
//fgit_commit Last_commit;
typedef struct
{
	unsigned int size;
	fgit_commit commits[1024];
}fgit_commits;

//git 的路径
typedef struct  
{
	char path_src[MAX_PATH];
	char path_dis[MAX_PATH];
}fgit_path_2d;

//git 所有提交的所有路径
typedef struct
{
	int size;
	fgit_path_2d paths[MAX_PATH * 2];
}fgit_path_2ds;
fgit_path_2ds git_path_2ds;

//文件版本操作类型
typedef enum
{
	NONE_File,
	ADD_FILE,
	SUBTRACT_FILE,
	OVERLAP_FILE,
}eversion_operation_type;

//单个文件的版本
typedef struct
{
	eversion_operation_type operation_type;
	unsigned int file_size;
	char file_name[MAX_PATH];//
	simple_c_guid crc;
}fgit_version;

//整体文件的版本
typedef struct
{
	unsigned int size;
	fgit_version paths[1024];
}fgit_versions;
fgit_versions versions;

//整体文件版本列表
typedef struct
{
	unsigned int size;
	fgit_versions paths[1024];
}fgit_versions_list;

//Engine core
//////////////////////////////////////////////////////////////////////////
void init_path(fpath *p);
void init_git_commits(fgit_commits *git_commits);

void git_clone_funcation();
void version_iteration_update();

void string_to_path(const char *data,fpath* p);
void path_to_string( char* data,const fpath* p);

char *get_git_commit(fgit_commit *git_commit);
char *git_commit_to_string(const fgit_commit *git_commit,char *buf);
void string_to_git_commit(fgit_commit *git_commit,const char *buf);
void string_to_git_commits(fgit_commits *git_commit, const char *buf);
void string_to_ignore_path(const char *buf);
void string_to_ignore_suffix(const char *buf);

void compare_list(const fgit_versions* server_version_list, const def_c_paths* local_paths, def_c_paths* out_paths);

void init_versions(fgit_versions *in_versions);
void init_commit(fgit_commit *out_commit);
void init_git_path_2ds(fgit_path_2ds *path_2ds);

void add_git_versions(const char *int_path,eversion_operation_type type, fgit_versions *out_versions);
void versions_to_string(char *buf,const fgit_versions *in_versions);
void string_to_versions(const char *buf,fgit_versions *in_versions);
//core
void init_engine(int argc, char *argv[]);
void engine_loop();
void exit_engine();

//
void read_user();

//
void save_user();

//get
const char *get_git_version_filename();
const char *get_git_current_version_filename();
const char *get_git_path();
char *get_git_client_cache_path();
char *get_git_project_remote_url();
char *get_current_time();
char *get_git_project_path();
char *get_git_local_user_filename();
unsigned char get_protocal();

bool is_exit_ignore(const char *path);
//log
//////////////////////////////////////////////////////////////////////////

协议号

#pragma once
//Copyright (C) RenZhai.2019.All Rights Reserved.
//作者 人宅
//该c库的详细源码讲解在AboutCG 《手把手入门硬核c语言》视频工程里面:
//https://www.aboutcg.org/courseDetails/902/introduce
//希望学习其他方面技术 比如做UE4游戏, 可以访问下列网址:
//https://zhuanlan.zhihu.com/p/60117613
//
//bibi可以看到各个人宅系列教程介绍:
//https://space.bilibili.com/29544409
//
//个人博客网站
////renzhai.net
//
//关于本套案例的详细操作 :
//文字版本(详细):
//https://zhuanlan.zhihu.com/p/144558934
//视频版本:
//https://www.bilibili.com/video/BV1x5411s7s3
#include "git.h"

_CRT_BEGIN_C_HEADER

typedef enum
{
	NONE = 0,						//什么都不发生
	HELLO,							//客户端 向服务器 发送 确认 用于链接
	HEI,							//服务器反馈
	COMMIT,							//提交信息
	COMMIT_VERSION_LIST,			//提交版本列表
	VERSION_LOG,					//请求服务端 版本提交日志
	VERSION_STATUS,					//版本修改内容 本次版本状态
	PROTOCAL_ERROR,					//在服务器发生的错误信息
	VERSION_PROTOCAL,				//获取最新服务器版本信息
	VERSION_LIST,					//获取最新服务器版本列表
	VERSION_NEST,					//获取在本版本号的基础上的下一个版本号
	VERSION_NEST_COMPLETE,			//服务器版本列表发送成功
	VERSION_CLASH,					//检测 冲突
	CLASH_CONTENT,					//获取 冲突 内容
	NO_CLASH,						//无冲突
	CHECK_REMOVE_FILENAME,			//检查有没有存在客户端删除的副本 有就通知服务端删除该数据
	REMOVE_CONTENT,					//提交移除的内容
	GIT_CLONE,						//克隆服务端数据
	FILE_EXIT,						//文件是否存在
	FIND_VERSION_LIST,				//根据版本路径寻找数据对应版本内容
	CONNECT_TIME_OUT,				//连接超时
	REMOVE_LOCAL_REQUEST,			//发送客户端移除 协议
	SAVE_VERSION_REQUEST,			//通知服务器 存储当前版本
	GIT_RESET_VERSION,				//还原版本
}egit_protocal_type;

_CRT_END_C_HEADER

特别提示

本git小程序的内存管理非动态内存,是固定分配一定份额的内存,如果用完就会产生奔溃,支持的项目为小型项目,

比如c或者c++源码等内容版本更新迭代,以后可以考虑扩展为动态内存。

本程序仅仅提供学习,在学习本程序请结合源码学习.

发表评论

一.商业版本和学习版本的对比

二.您还未登陆哦

三.该资源出自以下课程