How to use the Pure Git tool

The Pure Git tool is a model and UI of a git repository. It allows you to explore every aspect of a git repository through a set of interlinked objects with custom views. A set of operations supports a number of basic git operations such as commit, init, clone, fetch, merge, pull and push.

Contrary to Iceberg, Pure Git does explicitely not model Pharo code packages. The goal is to offer a one on one model of well know git concepts.

Getting started

Pure Git uses the git CLI interface the basics of which are necessary to continue. SeeUsing Libgit-CLI as an alternative to Libgit2 FFI in Iceberg

Make sure everything is OK as reported by the platform class.

currentIceGitCliPlatform
	<gtExample>

	^ IceGitCliPlatform current
    

On disk repositories

The only thing needed to get started is a directory containing an on disk git repository.

exampleGt4Git
	<gtExample>
	<noTest>

	| repository |

	repository := PureGitRepository on: (IceRepository repositoryNamed: 'gt4git') location.

	self assert: repository exists.

	^ repository
    
exampleGToolkit
	<gtExample>
	<noTest>

	| repository |

	repository := PureGitRepository on: (IceRepository repositoryNamed: 'gtoolkit') location.

	self assert: repository exists.

	^ repository
    

Cloning from a remote

In most cases, you will start by cloning a git repository from a remote (location/server).

exampleIcebergGitCli
	<gtExample>
	<noTest>

	| workingDirectory gitUrl repository |

	workingDirectory := FileLocator temp resolve / 'example-clone'.
	workingDirectory exists ifTrue: [ workingDirectory deleteAll ].

	gitUrl := PureGitUrl with: 'git@github.com:feenkcom/iceberg-git-cli.git'.

	self assert: gitUrl isScpUrl.
	self assert: gitUrl ownerName equals: 'feenkcom'.
	self assert: gitUrl repositoryName equals: 'iceberg-git-cli'.

	repository := gitUrl cloneWithOwnerPrefixIn: workingDirectory.

	self 
		assert: repository location 
		equals: workingDirectory / gitUrl ownerName / gitUrl repositoryName.

	self assert: repository exists.
	self assert: repository hasHead.
	self assert: repository branch upstream remote url equals: gitUrl url.

	^ repository
    

Exploring git concepts

At its core, git is a content addressable key / value store where values are bytes and keys are hashes of those bytes. The main types of values are blobs, commits and trees.

exampleContentAddressableObjectStore
	<gtExample>
	<noTest>

	| repository id blob idChanged blobChanged |

	repository := self exampleSecondCommitInRepository.

	id := PureGitBlob hashText: self exampleFileContentsInRepository.

	self assert: id isString.
	self assert: id size equals: 40.
	self assert: (id allSatisfy: [ :each | '0123456789abcdef' includes: each ]).

	blob := repository resolveBlob: id.

	self assert: blob id equals: id.
	self assert: blob text equals: self exampleFileContentsInRepository.

	idChanged := PureGitBlob hashText: self exampleFileContentsChangedInRepository.
	blobChanged := repository resolveBlob: idChanged.

	self assert: blobChanged id equals: idChanged.
	self assert: blobChanged text equals: self exampleFileContentsChangedInRepository.

	self assert: id ~= idChanged.
	self assert: blob contents ~= blobChanged contents.

	self
		assert: (repository location / self exampleFilename) contents
		equals: self exampleFileContentsChanged.

	^ Array with: blob with: blobChanged
    

A git commit is an elegant and efficient snapshot of the state of the whole repository's working tree.

exampleAnatomyOfACommit
	<gtExample>
	<noTest>
	
	| repository commit tree entry blob parent parentBlob changes |

	repository := self exampleSecondCommitInRepository.

	self
		assert: (repository location / self exampleFilename) contents
		equals: self exampleFileContentsChanged.

	commit := repository head.
	tree := commit tree.
	entry := tree entryNamed: self exampleFilename.
	blob := entry resolve.

	self assert: commit comment equals: self exampleSecondCommitComment.
	self assert: blob text equals: self exampleFileContentsChangedInRepository.
	self 
		assert: blob id
		equals: (PureGitBlob hashText: self exampleFileContentsChangedInRepository).
	
	self assert: commit hasSingleParent.

	parent := commit parent.
	parentBlob := (parent tree entryNamed: self exampleFilename) resolve.

	self assert: commit id ~= parent id.
	self assert: blob id ~= parentBlob id.
	self assert: parentBlob text equals: self exampleFileContentsInRepository.

	changes := commit changesToParent.

	self assert: changes diffs size equals: 1.
	self assert: changes firstDiff numberOfLinesAdded equals: 1.
	self assert: changes firstDiff numberOfLinesRemoved equals: 0.
	self
		assert: changes firstDiff changeChunks first oldContents lines
		equals: self exampleFileContents lines.
	self
		assert: changes firstDiff changeChunks first newContents lines
		equals: self exampleFileContentsChanged lines.

	^ commit