README.md in git-1.7.0 vs README.md in git-1.8.0

- old
+ new

@@ -1,24 +1,49 @@ -# Git Library for Ruby +<!-- +# @markup markdown +# @title README +--> -Library for using Git in Ruby. +# The Git Gem +The Git Gem provides an API that can be used to create, read, and manipulate +Git repositories by wrapping system calls to the `git` binary. The API can be +used for working with Git in complex interactions including branching and +merging, object inspection and manipulation, history, patch generation and +more. + ## Homepage -Git public hosting of the project source code is at: +The project source code is at: http://github.com/ruby-git/ruby-git +## Documentation + +Detailed documentation can be found at: + +https://rubydoc.info/gems/git/Git.html + +Get started by obtaining a repository object by: + +* opening an existing working copy with [Git.open](https://rubydoc.info/gems/git/Git#open-class_method) +* initializing a new repository with [Git.init](https://rubydoc.info/gems/git/Git#init-class_method) +* cloning a repository with [Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method) + +Methods that can be called on a repository object are documented in [Git::Base](https://rubydoc.info/gems/git/Git/Base) + ## Install You can install Ruby/Git like this: - $ sudo gem install git +``` +sudo gem install git +``` ## Code Status -* [![Build Status](https://travis-ci.org/ruby-git/ruby-git.svg?branch=master)](https://travis-ci.org/ruby-git/ruby-git) +* [![Build Status](https://github.com/ruby-git/ruby-git/workflows/CI/badge.svg?branch=master)](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI) * [![Code Climate](https://codeclimate.com/github/ruby-git/ruby-git.png)](https://codeclimate.com/github/ruby-git/ruby-git) * [![Gem Version](https://badge.fury.io/rb/git.svg)](https://badge.fury.io/rb/git) ## Major Objects @@ -39,261 +64,280 @@ **Git::Log** - An Enumerable object that references all the `Git::Object::Commit` objects that encompass your log query, which can be constructed through methods on the `Git::Log object`, like: `@git.log(20).object("some_file").since("2 weeks ago").between('v2.6', 'v2.7').each { |commit| [block] }` + **Git::Worktrees** - Enumerable object that holds `Git::Worktree objects`. + ## Examples Here are a bunch of examples of how to use the Ruby/Git package. Ruby < 1.9 will require rubygems to be loaded. ```ruby - require 'rubygems' +require 'rubygems' ``` Require the 'git' gem. ```ruby - require 'git' +require 'git' ``` Git env config ```ruby - Git.configure do |config| - # If you want to use a custom git binary - config.binary_path = '/git/bin/path' +Git.configure do |config| + # If you want to use a custom git binary + config.binary_path = '/git/bin/path' - # If you need to use a custom SSH script - config.git_ssh = '/path/to/ssh/script' - end + # If you need to use a custom SSH script + config.git_ssh = '/path/to/ssh/script' +end ``` _NOTE: Another way to specify where is the `git` binary is through the environment variable `GIT_PATH`_ Here are the operations that need read permission only. ```ruby - g = Git.open(working_dir, :log => Logger.new(STDOUT)) +g = Git.open(working_dir, :log => Logger.new(STDOUT)) - g.index - g.index.readable? - g.index.writable? - g.repo - g.dir +g.index +g.index.readable? +g.index.writable? +g.repo +g.dir - g.log # returns array of Git::Commit objects - g.log.since('2 weeks ago') - g.log.between('v2.5', 'v2.6') - g.log.each {|l| puts l.sha } - g.gblob('v2.5:Makefile').log.since('2 weeks ago') +g.log # returns array of Git::Commit objects +g.log.since('2 weeks ago') +g.log.between('v2.5', 'v2.6') +g.log.each {|l| puts l.sha } +g.gblob('v2.5:Makefile').log.since('2 weeks ago') - g.object('HEAD^').to_s # git show / git rev-parse - g.object('HEAD^').contents - g.object('v2.5:Makefile').size - g.object('v2.5:Makefile').sha +g.object('HEAD^').to_s # git show / git rev-parse +g.object('HEAD^').contents +g.object('v2.5:Makefile').size +g.object('v2.5:Makefile').sha - g.gtree(treeish) - g.gblob(treeish) - g.gcommit(treeish) +g.gtree(treeish) +g.gblob(treeish) +g.gcommit(treeish) - commit = g.gcommit('1cc8667014381') +commit = g.gcommit('1cc8667014381') - commit.gtree - commit.parent.sha - commit.parents.size - commit.author.name - commit.author.email - commit.author.date.strftime("%m-%d-%y") - commit.committer.name - commit.date.strftime("%m-%d-%y") - commit.message +commit.gtree +commit.parent.sha +commit.parents.size +commit.author.name +commit.author.email +commit.author.date.strftime("%m-%d-%y") +commit.committer.name +commit.date.strftime("%m-%d-%y") +commit.message - tree = g.gtree("HEAD^{tree}") +tree = g.gtree("HEAD^{tree}") - tree.blobs - tree.subtrees - tree.children # blobs and subtrees +tree.blobs +tree.subtrees +tree.children # blobs and subtrees - g.revparse('v2.5:Makefile') +g.revparse('v2.5:Makefile') - g.branches # returns Git::Branch objects - g.branches.local - g.branches.remote - g.branches[:master].gcommit - g.branches['origin/master'].gcommit +g.branches # returns Git::Branch objects +g.branches.local +g.branches.remote +g.branches[:master].gcommit +g.branches['origin/master'].gcommit - g.grep('hello') # implies HEAD - g.blob('v2.5:Makefile').grep('hello') - g.tag('v2.5').grep('hello', 'docs/') - g.describe() - g.describe('0djf2aa') - g.describe('HEAD', {:all => true, :tags => true}) +g.grep('hello') # implies HEAD +g.blob('v2.5:Makefile').grep('hello') +g.tag('v2.5').grep('hello', 'docs/') +g.describe() +g.describe('0djf2aa') +g.describe('HEAD', {:all => true, :tags => true}) - g.diff(commit1, commit2).size - g.diff(commit1, commit2).stats - g.diff(commit1, commit2).name_status - g.gtree('v2.5').diff('v2.6').insertions - g.diff('gitsearch1', 'v2.5').path('lib/') - g.diff('gitsearch1', @git.gtree('v2.5')) - g.diff('gitsearch1', 'v2.5').path('docs/').patch - g.gtree('v2.5').diff('v2.6').patch +g.diff(commit1, commit2).size +g.diff(commit1, commit2).stats +g.diff(commit1, commit2).name_status +g.gtree('v2.5').diff('v2.6').insertions +g.diff('gitsearch1', 'v2.5').path('lib/') +g.diff('gitsearch1', @git.gtree('v2.5')) +g.diff('gitsearch1', 'v2.5').path('docs/').patch +g.gtree('v2.5').diff('v2.6').patch - g.gtree('v2.5').diff('v2.6').each do |file_diff| - puts file_diff.path - puts file_diff.patch - puts file_diff.blob(:src).contents - end +g.gtree('v2.5').diff('v2.6').each do |file_diff| + puts file_diff.path + puts file_diff.patch + puts file_diff.blob(:src).contents +end - g.config('user.name') # returns 'Scott Chacon' - g.config # returns whole config hash +g.worktrees # returns Git::Worktree objects +g.worktrees.count +g.worktrees.each do |worktree| + worktree.dir + worktree.gcommit + worktree.to_s +end - g.tags # returns array of Git::Tag objects +g.config('user.name') # returns 'Scott Chacon' +g.config # returns whole config hash - g.show() - g.show('HEAD') - g.show('v2.8', 'README.md') +g.tags # returns array of Git::Tag objects - Git.ls_remote('https://github.com/ruby-git/ruby-git.git') # returns a hash containing the available references of the repo. - Git.ls_remote('/path/to/local/repo') - Git.ls_remote() # same as Git.ls_remote('.') +g.show() +g.show('HEAD') +g.show('v2.8', 'README.md') +Git.ls_remote('https://github.com/ruby-git/ruby-git.git') # returns a hash containing the available references of the repo. +Git.ls_remote('/path/to/local/repo') +Git.ls_remote() # same as Git.ls_remote('.') ``` And here are the operations that will need to write to your git repository. ```ruby - g = Git.init - Git.init('project') - Git.init('/home/schacon/proj', - { :repository => '/opt/git/proj.git', - :index => '/tmp/index'} ) +g = Git.init + Git.init('project') + Git.init('/home/schacon/proj', + { :repository => '/opt/git/proj.git', + :index => '/tmp/index'} ) - g = Git.clone(URI, NAME, :path => '/tmp/checkout') - g.config('user.name', 'Scott Chacon') - g.config('user.email', 'email@email.com') +g = Git.clone(URI, NAME, :path => '/tmp/checkout') +g.config('user.name', 'Scott Chacon') +g.config('user.email', 'email@email.com') - g.add # git add -- "." - g.add(:all=>true) # git add --all -- "." - g.add('file_path') # git add -- "file_path" - g.add(['file_path_1', 'file_path_2']) # git add -- "file_path_1" "file_path_2" +# Clone can take an optional logger +logger = Logger.new +g = Git.clone(URI, NAME, :log => logger) - g.remove() # git rm -f -- "." - g.remove('file.txt') # git rm -f -- "file.txt" - g.remove(['file.txt', 'file2.txt']) # git rm -f -- "file.txt" "file2.txt" - g.remove('file.txt', :recursive => true) # git rm -f -r -- "file.txt" - g.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt" +g.add # git add -- "." +g.add(:all=>true) # git add --all -- "." +g.add('file_path') # git add -- "file_path" +g.add(['file_path_1', 'file_path_2']) # git add -- "file_path_1" "file_path_2" - g.commit('message') - g.commit_all('message') +g.remove() # git rm -f -- "." +g.remove('file.txt') # git rm -f -- "file.txt" +g.remove(['file.txt', 'file2.txt']) # git rm -f -- "file.txt" "file2.txt" +g.remove('file.txt', :recursive => true) # git rm -f -r -- "file.txt" +g.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt" - g = Git.clone(repo, 'myrepo') - g.chdir do - new_file('test-file', 'blahblahblah') - g.status.changed.each do |file| - puts file.blob(:index).contents - end - end +g.commit('message') +g.commit_all('message') - g.reset # defaults to HEAD - g.reset_hard(Git::Commit) +g = Git.clone(repo, 'myrepo') +g.chdir do +new_file('test-file', 'blahblahblah') +g.status.changed.each do |file| + puts file.blob(:index).contents +end +end - g.branch('new_branch') # creates new or fetches existing - g.branch('new_branch').checkout - g.branch('new_branch').delete - g.branch('existing_branch').checkout - g.branch('master').contains?('existing_branch') +g.reset # defaults to HEAD +g.reset_hard(Git::Commit) - g.checkout('new_branch') - g.checkout(g.branch('new_branch')) +g.branch('new_branch') # creates new or fetches existing +g.branch('new_branch').checkout +g.branch('new_branch').delete +g.branch('existing_branch').checkout +g.branch('master').contains?('existing_branch') - g.branch(name).merge(branch2) - g.branch(branch2).merge # merges HEAD with branch2 +g.checkout('new_branch') +g.checkout(g.branch('new_branch')) - g.branch(name).in_branch(message) { # add files } # auto-commits - g.merge('new_branch') - g.merge('origin/remote_branch') - g.merge(g.branch('master')) - g.merge([branch1, branch2]) +g.branch(name).merge(branch2) +g.branch(branch2).merge # merges HEAD with branch2 - g.merge_base('branch1', 'branch2') +g.branch(name).in_branch(message) { # add files } # auto-commits +g.merge('new_branch') +g.merge('new_branch', 'merge commit message', no_ff: true) +g.merge('origin/remote_branch') +g.merge(g.branch('master')) +g.merge([branch1, branch2]) - r = g.add_remote(name, uri) # Git::Remote - r = g.add_remote(name, Git::Base) # Git::Remote +g.merge_base('branch1', 'branch2') - g.remotes # array of Git::Remotes - g.remote(name).fetch - g.remote(name).remove - g.remote(name).merge - g.remote(name).merge(branch) +r = g.add_remote(name, uri) # Git::Remote +r = g.add_remote(name, Git::Base) # Git::Remote - g.fetch - g.fetch(g.remotes.first) - g.fetch('origin', {:ref => 'some/ref/head'} ) +g.remotes # array of Git::Remotes +g.remote(name).fetch +g.remote(name).remove +g.remote(name).merge +g.remote(name).merge(branch) - g.pull - g.pull(Git::Repo, Git::Branch) # fetch and a merge +g.fetch +g.fetch(g.remotes.first) +g.fetch('origin', {:ref => 'some/ref/head'} ) - g.add_tag('tag_name') # returns Git::Tag - g.add_tag('tag_name', 'object_reference') - g.add_tag('tag_name', 'object_reference', {:options => 'here'}) - g.add_tag('tag_name', {:options => 'here'}) +g.pull +g.pull(Git::Repo, Git::Branch) # fetch and a merge - Options: - :a | :annotate - :d - :f - :m | :message - :s +g.add_tag('tag_name') # returns Git::Tag +g.add_tag('tag_name', 'object_reference') +g.add_tag('tag_name', 'object_reference', {:options => 'here'}) +g.add_tag('tag_name', {:options => 'here'}) - g.delete_tag('tag_name') +Options: + :a | :annotate + :d + :f + :m | :message + :s - g.repack +g.delete_tag('tag_name') - g.push - g.push(g.remote('name')) +g.repack + +g.push +g.push(g.remote('name')) + +g.worktree('/tmp/new_worktree').add +g.worktree('/tmp/new_worktree', 'branch1').add +g.worktree('/tmp/new_worktree').remove +g.worktrees.prune ``` Some examples of more low-level index and tree operations ```ruby - g.with_temp_index do +g.with_temp_index do - g.read_tree(tree3) # calls self.index.read_tree - g.read_tree(tree1, :prefix => 'hi/') + g.read_tree(tree3) # calls self.index.read_tree + g.read_tree(tree1, :prefix => 'hi/') - c = g.commit_tree('message') - # or # - t = g.write_tree - c = g.commit_tree(t, :message => 'message', :parents => [sha1, sha2]) + c = g.commit_tree('message') + # or # + t = g.write_tree + c = g.commit_tree(t, :message => 'message', :parents => [sha1, sha2]) - g.branch('branch_name').update_ref(c) - g.update_ref(branch, c) + g.branch('branch_name').update_ref(c) + g.update_ref(branch, c) - g.with_temp_working do # new blank working directory - g.checkout - g.checkout(another_index) - g.commit # commits to temp_index - end - end + g.with_temp_working do # new blank working directory + g.checkout + g.checkout(another_index) + g.commit # commits to temp_index + end +end - g.set_index('/path/to/index') +g.set_index('/path/to/index') - g.with_index(path) do - # calls set_index, then switches back after - end +g.with_index(path) do + # calls set_index, then switches back after +end - g.with_working(dir) do - # calls set_working, then switches back after - end +g.with_working(dir) do +# calls set_working, then switches back after +end - g.with_temp_working(dir) do - g.checkout_index(:prefix => dir, :path_limiter => path) - # do file work - g.commit # commits to index - end +g.with_temp_working(dir) do + g.checkout_index(:prefix => dir, :path_limiter => path) + # do file work + g.commit # commits to index +end ``` ## License licensed under MIT License Copyright (c) 2008 Scott Chacon. See LICENSE for further details.