Skip to content

Instantly share code, notes, and snippets.

@song940
Last active February 9, 2022 07:12
Show Gist options
  • Save song940/a41ffef47048f097e85088b39e63d476 to your computer and use it in GitHub Desktop.
Save song940/a41ffef47048f097e85088b39e63d476 to your computer and use it in GitHub Desktop.
// https://kushagra.dev/blog/build-git-learn-git/
function Git(name) {
this.name = name;
this.lastCommitId = -1;
this.branches = [];
const master = new Branch("master", null);
this.branches.push(master);
this.HEAD = master;
}
Git.prototype.commit = function (message) {
const commit = new Commit(++this.lastCommitId, this.HEAD.commit, message);
this.HEAD.commit = commit;
return commit;
};
Git.prototype.log = function () {
const history = [];
let { commit } = this.HEAD;
while (commit) {
history.push(commit);
commit = commit.parent;
}
return history;
}
Git.prototype.checkout = function (branchName) {
// Loop through all branches and see if we have a branch
// called `branchName`.
for (const branch of this.branches) {
if (branch.name === branchName) {
console.log("Switched to existing branch: " + branchName);
this.HEAD = branch
return branch;
}
}
// If branch was not found, create a new one.
const newBranch = new Branch(branchName, this.HEAD.commit);
this.branches.push(newBranch);
this.HEAD = newBranch;
console.log("Switched to new branch: " + branchName);
return newBranch;
};
function Commit(id, parent, message) {
this.id = id;
this.parent = parent;
this.message = message;
}
function Branch(name, commit) {
this.name = name;
this.commit = commit;
}
// Maps the array of commits into a string of commit ids.
// For [C2, C1,C3], it returns "2-1-0"
function historyToIdMapper(history) {
var ids = history.map(function(commit) {
return commit.id;
});
return ids.join("-");
}
var repo = new Git("test");
repo.commit("Initial commit");
repo.commit("Change 1");
console.assert(historyToIdMapper(repo.log()) === "1-0"); // Should show 2 commits.
repo.checkout("testing");
repo.commit("Change 3");
console.assert(historyToIdMapper(repo.log()) === "2-1-0"); // Should show 3 commits.
repo.checkout("master");
console.assert(historyToIdMapper(repo.log()) === "1-0"); // Should show 2 commits. Master unpolluted.
repo.commit("Change 3");
console.assert(historyToIdMapper(repo.log()) === "3-1-0"); // Continue on master with 4th commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment