diff --git a/docs/git/checkout.md b/docs/git/checkout.md index d9a9cd6..210223e 100644 --- a/docs/git/checkout.md +++ b/docs/git/checkout.md @@ -10,7 +10,7 @@ description: Clone a repository by its provided URL into a newly created directo Switch from the default branch of a repository (working directory) to a new or existing one, syncing any file changes. All future actions are associated with this branch. -## Context-aware checking out :material-new-box:{.new-feature title="Feature added on the 23rd March of 2023"} +## Context-aware checking out During a checkout, `gitz` inspects the repository for the existence of a branch and intelligently switches between creating a new one or checking out the existing reference. diff --git a/docs/git/checks.md b/docs/git/checks.md index 23b2002..4e4a35f 100644 --- a/docs/git/checks.md +++ b/docs/git/checks.md @@ -1,5 +1,6 @@ --- icon: material/clipboard-check-outline +status: new title: Git checks and how to use them description: A series of inbuilt check for inspecting the environment and current repository --- @@ -32,7 +33,7 @@ func main() { } ``` -## Checking the integrity of a Repository +## Checking the integrity of a Repository :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} Check the integrity of a repository by running a series of tests and capturing the results for inspection. @@ -55,8 +56,11 @@ func main() { } fmt.Printf("Default Branch: %s\n", repo.DefaultBranch) - fmt.Printf("Shallow Clone: %t\n", repo.ShallowClone) fmt.Printf("Detached Head: %t\n", repo.DetachedHead) + fmt.Printf("Origin: %s\n", repo.Origin) + fmt.Printf("Remotes: %#v\n", repo.Remotes) + fmt.Printf("Root Directory: %s\n", repo.RootDir) + fmt.Printf("Shallow Clone: %t\n", repo.ShallowClone) } ``` @@ -64,6 +68,9 @@ Example output when checking the integrity of a repository cloned within a CI sy ```{ .text .no-select .no-copy } Default Branch: main -Shallow Clone: false Detached Head: true +Origin: git@github.com:purpleclay/gitz.git +Remotes: map[string]string{"origin":"git@github.com:purpleclay/gitz.git"} +Root Directory: /dev/github.com/purpleclay/gitz +Shallow Clone: false ``` diff --git a/docs/git/clone.md b/docs/git/clone.md index e9ef612..eb62e65 100644 --- a/docs/git/clone.md +++ b/docs/git/clone.md @@ -1,5 +1,6 @@ --- icon: material/sheep +status: new title: Cloning a repository description: Clone a repository by its provided URL into a newly created directory --- @@ -33,7 +34,7 @@ func main() { } ``` -## With a truncated history :material-new-box:{.new-feature title="Feature added on the 23rd March of 2023"} +## With a truncated history If a complete git history isn't desirable, a faster approach to cloning is to provide a clone depth using the `WithDepth` option. This results in a truncated history, better known as a `shallow clone`. Great for large established repositories. @@ -77,7 +78,7 @@ Printing the log results in: feat: add options that can configure the size of the repository during a clone ``` -## Without tags :material-new-box:{.new-feature title="Feature added on the 23rd March of 2023"} +## Without tags To further streamline a clone, the `WithNoTags` option prevents the downloading of tags from the remote. @@ -117,7 +118,7 @@ Printing the output results in: repository has no tags ``` -## Clone into a named directory :material-new-box:{.new-feature title="Feature added on the 23rd March of 2023"} +## Clone into a named directory By default, git will always clone the repository into a directory based on the human-friendly part of the clone URL. To clone into a different directory, use the `WithDirectory` option. @@ -141,7 +142,7 @@ func main() { } ``` -## Clone a branch or tag :material-new-box:{.new-feature title="Feature added on the 23rd March of 2023"} +## Clone a branch or tag Git will always clone and checkout the default branch of a repository. To change this behavior, provide a branch or tag reference with the `WithCheckoutRef` option. The latter results in a `detached HEAD` where the `HEAD` of a repository points to a specific commit reference. @@ -164,3 +165,7 @@ func main() { } } ``` + +## Providing git config at execution :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +You can provide git config through the `WithCloneConfig` option to only take effect during the execution of a `Clone`, removing the need to change config permanently. diff --git a/docs/git/commit.md b/docs/git/commit.md index 5af21ae..55f52c0 100644 --- a/docs/git/commit.md +++ b/docs/git/commit.md @@ -48,7 +48,7 @@ Date: Mon Feb 20 20:43:49 2023 +0000 feat: a brand new feature ``` -## Allowing an empty commit :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +## Allowing an empty commit You can create empty commits without staging any files using the `WithAllowEmpty` option. @@ -67,7 +67,7 @@ func main() { } ``` -## Signing a commit using GPG :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +## Signing a commit using GPG Any commit to a repository can be GPG signed by an author to prove its authenticity through GPG verification. By setting the `commit.gpgSign` and `user.signingKey` git config options, GPG signing, can become an automatic process. `gitz` provides options to control this process and manually overwrite existing settings per commit. @@ -141,3 +141,7 @@ func main() { git.WithNoGpgSign()) } ``` + +## Providing git config at execution :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +You can provide git config through the `WithCommitConfig` option to only take effect during the execution of a `Commit`, removing the need to change config permanently. diff --git a/docs/git/config.md b/docs/git/config.md index 6211ae9..c805042 100644 --- a/docs/git/config.md +++ b/docs/git/config.md @@ -1,6 +1,5 @@ --- icon: material/keyboard-settings-outline -status: new title: Managing your git config description: Get and set your local git repository config --- @@ -11,7 +10,7 @@ description: Get and set your local git repository config Manage settings within your local git config, changing the behavior of the git client. -## Retrieve all settings :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +## Retrieve all settings Retrieve all git config for the current repository using `Config`. @@ -43,7 +42,7 @@ The value for the config setting would be: purpleclay ``` -## Retrieve a batch of settings :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +## Retrieve a batch of settings A batch of settings can be retrieved using `ConfigL` (_local_), `ConfigS` (_system_), or `ConfigG` (_global_). A partial retrieval is not supported and will fail if any are missing. All values for a setting are retrieved and ordered by the latest. @@ -76,7 +75,7 @@ purpleclay ********************** ``` -## Update a batch of settings :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +## Update a batch of settings You can update multiple settings in a batch using `ConfigSetL` (_local_), `ConfigSetS` (_system_), or `ConfigSetG` (_global_). Pre-validation of config paths improves the chance of a successful update, but a partial batch may occur upon failure. diff --git a/docs/git/log.md b/docs/git/log.md index ad7bf50..0325dd4 100644 --- a/docs/git/log.md +++ b/docs/git/log.md @@ -174,7 +174,7 @@ d611a22c1a009bd74bc2c691b331b9df38828dae fix: typos in file content 9b342465255d1a8ec4f5517eef6049e5bcc8fb45 feat: a brand new feature ``` -### Resolving explicit file paths :material-new-box:{.new-feature title="Feature added on the 31st March of 2023"} +### Resolving explicit file paths Querying the log with explicit paths isn't supported and will return no history. Converting to a relative one can be achieved with the `ToRelativePath` helper, as it resolves paths against the root working directory of the current repository. diff --git a/docs/git/pull.md b/docs/git/pull.md index 1116f6e..44b29b7 100644 --- a/docs/git/pull.md +++ b/docs/git/pull.md @@ -1,5 +1,6 @@ --- icon: material/arrow-left-bold-box-outline +status: new title: Pulling the latest changes from a remote description: Pull all changes from a remote into the current working directory --- @@ -56,3 +57,7 @@ Fast-forward 1 file changed, 1 insertion(+) create mode 100644 folder/c.txt ``` + +## Providing git config at execution :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +You can provide git config through the `WithPullConfig` option to only take effect during the execution of a `Pull`, removing the need to change config permanently. diff --git a/docs/git/push.md b/docs/git/push.md index b408b7e..f26d245 100644 --- a/docs/git/push.md +++ b/docs/git/push.md @@ -117,9 +117,9 @@ func main() { } ``` -## Push a single branch or tag +## Push options -`PushRef` can be called to cherry-pick and push a single reference (_branch or tag_) back to the remote: +Support the transmission of arbitrary strings to the remote server using the `WithPushOptions` option. ```{ .go .select linenums="1" } package main @@ -133,18 +133,18 @@ import ( func main() { client, _ := git.NewClient() - // tag 0.1.0 has been created and is tracked locally + // all changes have been staged and committed locally - _, err := client.PushRef("0.1.0") + _, err := client.Push(git.WithPushOptions("ci.skip=true")) if err != nil { - log.Fatal("failed to push tag 0.1.0 to the remote") + log.Fatal("failed to push committed changes to the remote") } } ``` -## Push options :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +## Deleting references from the remote :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} -Support the transmission of arbitrary strings to the remote server using the `WithPushOptions` option. +Delete any number of references from the remote by using the `WithDeleteRefSpecs` option. ```{ .go .select linenums="1" } package main @@ -158,11 +158,15 @@ import ( func main() { client, _ := git.NewClient() - // all changes have been staged and committed locally + // a tag and branch have been deleted locally - _, err := client.Push(git.WithPushOptions("ci.skip=true")) + _, err := client.Push(git.WithDeleteRefSpecs("branch", "0.1.0")) if err != nil { - log.Fatal("failed to push committed changes to the remote") + log.Fatal("failed to delete references from the remote") } } ``` + +## Providing git config at execution :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +You can provide git config through the `WithPushConfig` option to only take effect during the execution of a `Push`, removing the need to change config permanently. diff --git a/docs/git/show.md b/docs/git/show.md new file mode 100644 index 0000000..f6cfcea --- /dev/null +++ b/docs/git/show.md @@ -0,0 +1,110 @@ +--- +icon: material/text-search +status: new +title: Inspect an object within a repository +description: Retrieve details about a specific object from within a repository +--- + +# Inspect an object within a repository + +[:simple-git:{ .git-icon } Git Documentation](https://git-scm.com/docs/git-show) + +Retrieve detailed information about an object within a repository by its unique reference. + +## Inspect a tag + +Detailed information about a tag, and its associated commit, can be retrieved from a repository by passing its reference to `ShowTags`. The GPG signature of the commit is also retrieved if present. + +```{ .go .select linenums="1" } +package main + +import ( + "fmt" + "time" + + git "github.com/purpleclay/gitz" +) + +func main() { + client, _ := git.NewClient() + + // Querying a tag from the gpg-import project + + tags, _ := client.ShowTags("0.3.2") + + tag := tags[0] + if tag.Annotation != nil { + fmt.Printf("Tagger: %s <%s>\n", + tag.Annotation.Tagger.Name, tag.Annotation.Tagger.Email) + fmt.Printf("TaggerDate: %s\n", + tag.Annotation.TaggerDate.Format(time.RubyDate)) + fmt.Printf("Message: %s\n\n", tag.Annotation.Message) + } + + fmt.Printf("Author: %s <%s>\n", + tag.Commit.Author.Name, tag.Commit.Author.Email) + fmt.Printf("AuthorDate: %s\n", + tag.Commit.AuthorDate.Format(time.RubyDate)) + fmt.Printf("Commit: %s <%s>\n", + tag.Commit.Committer.Name, tag.Commit.Committer.Email) + fmt.Printf("CommitDate: %s\n", + tag.Commit.CommitterDate.Format(time.RubyDate)) + fmt.Printf("Message: %s\n\n", tag.Commit.Message) + if tag.Commit.Signature != nil { + fmt.Printf("Fingerprint: %s\n", tag.Commit.Signature.Fingerprint) + } +} +``` + +```{ .text .no-select .no-copy } +Tagger: purpleclay +TaggerDate: Thu Jun 29 07:05:18 +0100 2023 +Message: chore: tagged for release 0.3.2 + +Author: Purple Clay +AuthorDate: Thu Jun 29 06:40:51 +0100 2023 +Commit: GitHub +CommitDate: Thu Jun 29 06:40:51 +0100 2023 +Message: fix: imported gpg key fails to sign when no tty is present (#33) +Fingerprint: 4AEE18********** +``` + +## Inspect a commit + +Retrieve information about a specific commit by passing its reference to `ShowCommits`. Including its GPG signature, if present. + +## Inspect a tree + +Call `ShowTrees` to retrieve a listing of all files and directories within a specific tree index of a repository. + +```{ .go .select linenums="1" } +package main + +import ( + "fmt" + + git "github.com/purpleclay/gitz" +) + +func main() { + client, _ := git.NewClient() + + // Query the gittest directory tree within gitz + + tree, _ := client.ShowTrees("ad4a68f6628ba9a6c367fe213eb8136fdb95ebcd") + for _, entry := range tree[0].Entries { + fmt.Printf("%s\n", entry) + } +} +``` + +```{ .text .no-select .no-copy } +log.go +log_test.go +repository.go +repository_test.go +``` + +## Inspect a blob + +Retrieve the contents of a file (blob) from a repository by passing its reference to `ShowBlobs`. diff --git a/docs/git/status.md b/docs/git/status.md new file mode 100644 index 0000000..d1dcfcf --- /dev/null +++ b/docs/git/status.md @@ -0,0 +1,88 @@ +--- +icon: material/format-list-checkbox +status: new +title: Inspecting the status of a repository +description: Check the status of the current repository and identify if any changes exist +--- + +# Inspecting the status of a repository + +[:simple-git:{ .git-icon } Git Documentation](https://git-scm.com/docs/git-status) + +Identify if any differences exist between the git staging area (_known as the index_) and the latest commit. + +## Porcelain status :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +To retrieve a parseable list of changes within a repository, call `PorcelainStatus`. Changes are listed using the porcelain V1 format, consisting of a two-character indicator followed by a path to the identified change. + +```{ .go .select linenums="1" } +package main + +import ( + "fmt" + "log" + + git "github.com/purpleclay/gitz" +) + +func main() { + client, _ := git.NewClient() + + // Add some files: + // new.txt + // staged.txt + status, _ := client.PorcelainStatus() + + for _, s := range status { + fmt.Printf("%s\n", s) + } +} +``` + +```{ .text .no-select .no-copy } +?? new.txt +A staged.txt +``` + +### Supported indicators + +A two-character indicator, `' A'`, denotes the status of a file. It should be read as its status within the index, followed by its status within the working tree. Staging a file will move it from the working tree to the index, moving the indicator from the right (`' A'`) to the left (`'A '`). + +```{ .text .no-select .no-copy } +'A' Added +'C' Copied +'D' Deleted +'!' Ignored +'M' Modified +'R' Renamed +'T' Type Changed (e.g. regular file to symlink) +'U' Updated +' ' Unmodified +'?' Untracked +``` + +## Check if a repository is clean :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +Calling `Clean` will return `true` if a repository has no outstanding changes. + +```{ .go .select linenums="1" } +package main + +import ( + "fmt" + "log" + + git "github.com/purpleclay/gitz" +) + +func main() { + client, _ := git.NewClient() + clean, _ := client.Clean() + + fmt.Printf("Is Clean: %t\n", clean) +} +``` + +```{ .text .no-select .no-copy } +Is Clean: true +``` diff --git a/docs/git/tag.md b/docs/git/tag.md index fa3d3c1..ea111c3 100644 --- a/docs/git/tag.md +++ b/docs/git/tag.md @@ -315,7 +315,15 @@ func main() { [^1]: Gitz defers the validation of a tag name to the git client. Any error is captured and returned back to the caller -## Signing a tag using GPG :material-new-box:{.new-feature title="Feature added on the 16th of May 2023"} +### Only delete local reference :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +To prevent a deletion from being pushed back to the remote, use the `WithLocalDelete` option. + +## Deleting multiple tags :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +Call `DeleteTags` if you need to delete a batch of tags and sync it with the remote. Use the `WithLocalDelete` option to prevent any deletion from being pushed back to the remote. + +## Signing a tag using GPG Any tag against a repository can be GPG signed by the tagger to prove its authenticity through GPG verification. By setting the `tag.gpgSign` and `user.signingKey` git config options, GPG signing, can become an automatic process. `gitz` provides options to control this process and manually overwrite existing settings per tag. @@ -387,3 +395,7 @@ func main() { client.Tag("0.1.0", git.WithSkipSigning()) } ``` + +## Providing git config at execution :material-new-box:{.new-feature title="Feature added on the 26th of July 2023"} + +You can provide git config through the `WithTagConfig` option to only take effect during the execution of a `Tag`, removing the need to change config permanently. diff --git a/mkdocs.yml b/mkdocs.yml index c4b814d..02397a1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -48,7 +48,9 @@ nav: - Git Checkout: git/checkout.md - Git Pull: git/pull.md - Git Push: git/push.md + - Git Show: git/show.md - Git Stage: git/stage.md + - Git Status: git/status.md - Git Commit: git/commit.md - Git Tag: git/tag.md - Git Log: git/log.md