Git原理分析

Git原理分析

js 复制代码
const Git = (function () {
    function Git(name) {
        this.name = name;
        this.lastCommitId = -1;
        this.branches=[];
        const master=new Branch('master',null);
        this.branches.push(master);//把最初的master放到分支中
        this.HEAD = master;//引用最后一次的commit对象
    }
    function Commit(id,parent, message) {
        //id和commit关联,id引用commit
        this.id = id;
        this.parent = parent;
        this.message = message;
    }
    function Branch(name, commit) {
        this.name = name;
        this.commit = commit;
    }
    Git.prototype.commit = function (message) {
        //先在git里创建lastCommitId,然后可以在commit里传递id和消息
        //内部的id会自动进行递增
        //父级传递git里面的属性
        const commit = new Commit(++this.lastCommitId,this.HEAD.commit, message)
        console.log(this, 'commit this')
        this.HEAD.commit = commit;//每次commit一更新,head就更新
        return commit;
    }
    Git.prototype.log = function () {
        let commit = this.HEAD.commit;
        const history=[];
        while (commit) {
            //循环提交,查找上一次提交
            //不断将最新的提交放到历史记录中
            history.push(commit);
            commit = commit.parent;
        }
        return history;
    }
    Git.prototype.checkout = function (branchName) {
        for (let branch of this.branches) {
            if (branch.name === branchName) {
                console.log(`切换到分支${branchName}`);
                this.HEAD = branch;
                //返回this方便链式调用
                return this;
            }
        }
        //如果找不到相应的分支,创建一个并且进行更新
        const newBranch = new Branch(branchName,this.HEAD.commit);
        this.branches.push(newBranch);
        this.HEAD = newBranch;
        console.log(`分支${branchName}不存在`);
        return this;
    }
    return Git;
})()
// const repo = new Git('my-repo')
// console.log(repo.commit('first commit'))
const repo = new Git('test');
repo.commit('Initial commit');
repo.commit('Change 1')
function historyToIdMapper(history){
    const ids= history.map(commit=>commit.id);
    return ids.join('-');
}
console.log(historyToIdMapper(repo.log())==='1-0')
repo.checkout('testing')
repo.commit('Change 3')
console.log(historyToIdMapper(repo.log())==='2-1-0')
repo.checkout('master')
console.log(historyToIdMapper(repo.log())==='1-0')

git 内需要传入一个名字和id。id是为了引用commit,每一次提交都会使得id增加一个。

commit 里面需要传入消息,id 还有一个父级内容。父级是为了可以跟踪到上一个commit。还需要在git里创建一个head。这种形式是以链表的形式进行,所以在log函数中可以不断循环往上找父级的commit。

同时,还有一个history数组来记录历史数据。

还有一个可以进行切换分支的函数checkout。这个函数可以查找当前名字的分支,如果没有就创建一个新的分支。一开始初始化一个master分支,在git中使用head属性初始化,是为了后面都一定会有一个分支。

然后在测试时,如果切换分支再切换回来,原来的分支id没有发生变化,还是原来的计数方式。

相关推荐
码厂一粒沙13 分钟前
【代码管理】git使用指南(新手向)
git
white-persist18 分钟前
Python实例方法与Python类的构造方法全解析
开发语言·前端·python·原型模式
新中地GIS开发老师1 小时前
Cesium 军事标绘入门:用 Cesium-Plot-JS 快速实现标绘功能
前端·javascript·arcgis·cesium·gis开发·地理信息科学
Superxpang1 小时前
前端性能优化
前端·javascript·vue.js·性能优化
左手吻左脸。1 小时前
解决el-select因为弹出层层级问题,不展示下拉选
javascript·vue.js·elementui
李白的故乡1 小时前
el-tree-select名字
javascript·vue.js·ecmascript
Rysxt_1 小时前
Element Plus 入门教程:从零开始构建 Vue 3 界面
前端·javascript·vue.js
隐含1 小时前
对于el-table中自定义表头中添加el-popover会弹出两个的解决方案,分别针对固定列和非固定列来隐藏最后一个浮框。
前端·javascript·vue.js
大鱼前端1 小时前
Turbopack vs Webpack vs Vite:前端构建工具三分天下,谁将胜出?
前端·webpack·turbopack
你的人类朋友1 小时前
先用js快速开发,后续引入ts是否是一个好的实践?
前端·javascript·后端