зеркало из https://github.com/github/grit.git
convert readme to markdown
This commit is contained in:
Родитель
85fea86e27
Коммит
6bb41e4c10
|
@ -1,3 +1,7 @@
|
|||
==
|
||||
* Minor Enhancements
|
||||
* Convert readme to markdown
|
||||
|
||||
== 1.0.3 / 2009-02-13
|
||||
* Minor Enhancements
|
||||
* Added Grit::Commit#to_patch for plaintext formatted patches.
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
(The MIT License)
|
||||
|
||||
Copyright (c) 2007-2009 Tom Preston-Werner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,210 @@
|
|||
Grit
|
||||
====
|
||||
|
||||
Grit gives you object oriented read/write access to Git repositories via Ruby.
|
||||
The main goals are stability and performance. To this end, some of the
|
||||
interactions with Git repositories are done by shelling out to the system's
|
||||
`git` command, and other interactions are done with pure Ruby
|
||||
reimplementations of core Git functionality. This choice, however, is
|
||||
transparent to end users, and you need not know which method is being used.
|
||||
|
||||
This software was developed to power GitHub, and should be considered
|
||||
production ready. An extensive test suite is provided to verify its correctness.
|
||||
|
||||
Grit is maintained by Tom Preston-Werner, Scott Chacon, Chris Wanstrath, and
|
||||
PJ Hyett.
|
||||
|
||||
This documentation is accurate as of Grit 1.0.2.
|
||||
|
||||
|
||||
## Requirements #############################################################
|
||||
|
||||
* git (http://git-scm.com) tested with 1.6.0.2
|
||||
|
||||
|
||||
## Install ##################################################################
|
||||
|
||||
Easiest install is via RubyGems:
|
||||
|
||||
$ gem install grit
|
||||
|
||||
or
|
||||
|
||||
$ gem sources -a http://gems.github.com/ (you only need to do this once)
|
||||
$ gem install mojombo-grit
|
||||
|
||||
The gem from GitHub will generally be available sooner than the gem from
|
||||
Rubyforge. Both sources will eventually contain the same releases.
|
||||
|
||||
|
||||
## Source ###################################################################
|
||||
|
||||
Grit's Git repo is available on GitHub, which can be browsed at:
|
||||
|
||||
http://github.com/mojombo/grit
|
||||
|
||||
and cloned with:
|
||||
|
||||
git clone git://github.com/mojombo/grit.git
|
||||
|
||||
|
||||
## Usage ####################################################################
|
||||
|
||||
Grit gives you object model access to your Git repositories. Once you have
|
||||
created a `Repo` object, you can traverse it to find parent commits,
|
||||
trees, blobs, etc.
|
||||
|
||||
### Initialize a Repo object
|
||||
|
||||
The first step is to create a `Grit::Repo` object to represent your repo. In
|
||||
this documentation I include the `Grit` module to reduce typing.
|
||||
|
||||
require 'grit'
|
||||
include Grit
|
||||
repo = Repo.new("/Users/tom/dev/grit")
|
||||
|
||||
In the above example, the directory `/Users/tom/dev/grit` is my working
|
||||
directory and contains the `.git` directory. You can also initialize Grit with
|
||||
a bare repo.
|
||||
|
||||
repo = Repo.new("/var/git/grit.git")
|
||||
|
||||
### Getting a list of commits
|
||||
|
||||
From the `Repo` object, you can get a list of commits as an array of `Commit`
|
||||
objects.
|
||||
|
||||
repo.commits
|
||||
# => [#<Grit::Commit "e80bbd2ce67651aa18e57fb0b43618ad4baf7750">,
|
||||
#<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">,
|
||||
#<Grit::Commit "038af8c329ef7c1bae4568b98bd5c58510465493">,
|
||||
#<Grit::Commit "40d3057d09a7a4d61059bca9dca5ae698de58cbe">,
|
||||
#<Grit::Commit "4ea50f4754937bf19461af58ce3b3d24c77311d9">]
|
||||
|
||||
Called without arguments, `Repo#commits` returns a list of up to ten commits
|
||||
reachable by the **master** branch (starting at the latest commit). You can
|
||||
ask for commits beginning at a different branch, commit, tag, etc.
|
||||
|
||||
repo.commits('mybranch')
|
||||
repo.commits('40d3057d09a7a4d61059bca9dca5ae698de58cbe')
|
||||
repo.commits('v0.1')
|
||||
|
||||
You can specify the maximum number of commits to return.
|
||||
|
||||
repo.commits('master', 100)
|
||||
|
||||
If you need paging, you can specify a number of commits to skip.
|
||||
|
||||
repo.commits('master', 10, 20)
|
||||
|
||||
The above will return commits 21-30 from the commit list.
|
||||
|
||||
### The Commit object
|
||||
|
||||
`Commit` objects contain information about that commit.
|
||||
|
||||
head = repo.commits.first
|
||||
|
||||
head.id
|
||||
# => "e80bbd2ce67651aa18e57fb0b43618ad4baf7750"
|
||||
|
||||
head.parents
|
||||
# => [#<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">]
|
||||
|
||||
head.tree
|
||||
# => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
|
||||
|
||||
head.author
|
||||
# => #<Grit::Actor "Tom Preston-Werner <tom@mojombo.com>">
|
||||
|
||||
head.authored_date
|
||||
# => Wed Oct 24 22:02:31 -0700 2007
|
||||
|
||||
head.committer
|
||||
# => #<Grit::Actor "Tom Preston-Werner <tom@mojombo.com>">
|
||||
|
||||
head.committed_date
|
||||
# => Wed Oct 24 22:02:31 -0700 2007
|
||||
|
||||
head.message
|
||||
# => "add Actor inspect"
|
||||
|
||||
You can traverse a commit's ancestry by chaining calls to `#parents`.
|
||||
|
||||
repo.commits.first.parents[0].parents[0].parents[0]
|
||||
|
||||
The above corresponds to **master^^^** or **master~3** in Git parlance.
|
||||
|
||||
### The Tree object
|
||||
|
||||
A tree records pointers to the contents of a directory. Let's say you want
|
||||
the root tree of the latest commit on the **master** branch.
|
||||
|
||||
tree = repo.commits.first.tree
|
||||
# => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
|
||||
|
||||
tree.id
|
||||
# => "3536eb9abac69c3e4db583ad38f3d30f8db4771f"
|
||||
|
||||
Once you have a tree, you can get the contents.
|
||||
|
||||
contents = tree.contents
|
||||
# => [#<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">,
|
||||
#<Grit::Blob "81d2c27608b352814cbe979a6acd678d30219678">,
|
||||
#<Grit::Tree "c3d07b0083f01a6e1ac969a0f32b8d06f20c62e5">,
|
||||
#<Grit::Tree "4d00fe177a8407dbbc64a24dbfc564762c0922d8">]
|
||||
|
||||
This tree contains two `Blob` objects and two `Tree` objects. The trees are
|
||||
subdirectories and the blobs are files. Trees below the root have additional
|
||||
attributes.
|
||||
|
||||
contents.last.name
|
||||
# => "lib"
|
||||
|
||||
contents.last.mode
|
||||
# => "040000"
|
||||
|
||||
There is a convenience method that allows you to get a named sub-object
|
||||
from a tree.
|
||||
|
||||
tree / "lib"
|
||||
# => #<Grit::Tree "e74893a3d8a25cbb1367cf241cc741bfd503c4b2">
|
||||
|
||||
You can also get a tree directly from the repo if you know its name.
|
||||
|
||||
repo.tree
|
||||
# => #<Grit::Tree "master">
|
||||
|
||||
repo.tree("91169e1f5fa4de2eaea3f176461f5dc784796769")
|
||||
# => #<Grit::Tree "91169e1f5fa4de2eaea3f176461f5dc784796769">
|
||||
|
||||
### The Blob object
|
||||
|
||||
A blob represents a file. Trees often contain blobs.
|
||||
|
||||
blob = tree.contents.first
|
||||
# => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
|
||||
|
||||
A blob has certain attributes.
|
||||
|
||||
blob.id
|
||||
# => "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666"
|
||||
|
||||
blob.name
|
||||
# => "README.txt"
|
||||
|
||||
blob.mode
|
||||
# => "100644"
|
||||
|
||||
blob.size
|
||||
# => 7726
|
||||
|
||||
You can get the data of a blob as a string.
|
||||
|
||||
blob.data
|
||||
# => "Grit is a library to ..."
|
||||
|
||||
You can also get a blob directly from the repo if you know its name.
|
||||
|
||||
repo.blob("4ebc8aea50e0a67e000ba29a30809d0a7b9b2666")
|
||||
# => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
|
222
README.txt
222
README.txt
|
@ -1,222 +0,0 @@
|
|||
grit
|
||||
by Tom Preston-Werner, Scott Chacon
|
||||
http://github.com/mojombo/grit
|
||||
|
||||
== DESCRIPTION:
|
||||
|
||||
Grit is a Ruby library for extracting information from a git repository in an
|
||||
object oriented manner.
|
||||
|
||||
== REQUIREMENTS:
|
||||
|
||||
* git (http://git-scm.com) tested with 1.6.0.2
|
||||
|
||||
== INSTALL:
|
||||
|
||||
Easiest install is via RubyGems:
|
||||
|
||||
$ gem install grit
|
||||
|
||||
or
|
||||
|
||||
$ gem sources -a http://gems.github.com/ (you only need to do this once)
|
||||
$ gem install mojombo-grit
|
||||
|
||||
The gem from GitHub will generally be available sooner than the gem from
|
||||
Rubyforge. Both sources will eventually contain the same releases.
|
||||
|
||||
== SOURCE:
|
||||
|
||||
Grit's git repo is available on GitHub, which can be browsed at:
|
||||
|
||||
http://github.com/mojombo/grit
|
||||
|
||||
and cloned from:
|
||||
|
||||
git://github.com/mojombo/grit.git
|
||||
|
||||
== USAGE:
|
||||
|
||||
Grit gives you object model access to your git repository. Once you have
|
||||
created a repository object, you can traverse it to find parent commit(s),
|
||||
trees, blobs, etc.
|
||||
|
||||
= Initialize a Repo object
|
||||
|
||||
The first step is to create a Grit::Repo object to represent your repo. I
|
||||
include the Grit module so reduce typing.
|
||||
|
||||
require 'grit'
|
||||
include Grit
|
||||
repo = Repo.new("/Users/tom/dev/grit")
|
||||
|
||||
In the above example, the directory /Users/tom/dev/grit is my working
|
||||
repo and contains the .git directory. You can also initialize Grit with a
|
||||
bare repo.
|
||||
|
||||
repo = Repo.new("/var/git/grit.git")
|
||||
|
||||
= Getting a list of commits
|
||||
|
||||
From the Repo object, you can get a list of commits as an array of Commit
|
||||
objects.
|
||||
|
||||
repo.commits
|
||||
# => [#<Grit::Commit "e80bbd2ce67651aa18e57fb0b43618ad4baf7750">,
|
||||
#<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">,
|
||||
#<Grit::Commit "038af8c329ef7c1bae4568b98bd5c58510465493">,
|
||||
#<Grit::Commit "40d3057d09a7a4d61059bca9dca5ae698de58cbe">,
|
||||
#<Grit::Commit "4ea50f4754937bf19461af58ce3b3d24c77311d9">]
|
||||
|
||||
Called without arguments, Repo#commits returns a list of up to ten commits
|
||||
reachable by the master branch (starting at the latest commit). You can ask
|
||||
for commits beginning at a different branch, commit, tag, etc.
|
||||
|
||||
repo.commits('mybranch')
|
||||
repo.commits('40d3057d09a7a4d61059bca9dca5ae698de58cbe')
|
||||
repo.commits('v0.1')
|
||||
|
||||
You can specify the maximum number of commits to return.
|
||||
|
||||
repo.commits('master', 100)
|
||||
|
||||
If you need paging, you can specify a number of commits to skip.
|
||||
|
||||
repo.commits('master', 10, 20)
|
||||
|
||||
The above will return commits 21-30 from the commit list.
|
||||
|
||||
= The Commit object
|
||||
|
||||
Commit objects contain information about that commit.
|
||||
|
||||
head = repo.commits.first
|
||||
|
||||
head.id
|
||||
# => "e80bbd2ce67651aa18e57fb0b43618ad4baf7750"
|
||||
|
||||
head.parents
|
||||
# => [#<Grit::Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">]
|
||||
|
||||
head.tree
|
||||
# => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
|
||||
|
||||
head.author
|
||||
# => #<Grit::Actor "Tom Preston-Werner <tom@mojombo.com>">
|
||||
|
||||
head.authored_date
|
||||
# => Wed Oct 24 22:02:31 -0700 2007
|
||||
|
||||
head.committer
|
||||
# => #<Grit::Actor "Tom Preston-Werner <tom@mojombo.com>">
|
||||
|
||||
head.committed_date
|
||||
# => Wed Oct 24 22:02:31 -0700 2007
|
||||
|
||||
head.message
|
||||
# => "add Actor inspect"
|
||||
|
||||
You can traverse a commit's ancestry by chaining calls to #parents.
|
||||
|
||||
repo.commits.first.parents[0].parents[0].parents[0]
|
||||
|
||||
The above corresponds to master^^^ or master~3 in git parlance.
|
||||
|
||||
= The Tree object
|
||||
|
||||
A tree records pointers to the contents of a directory. Let's say you want
|
||||
the root tree of the latest commit on the master branch.
|
||||
|
||||
tree = repo.commits.first.tree
|
||||
# => #<Grit::Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
|
||||
|
||||
tree.id
|
||||
# => "3536eb9abac69c3e4db583ad38f3d30f8db4771f"
|
||||
|
||||
Once you have a tree, you can get the contents.
|
||||
|
||||
contents = tree.contents
|
||||
# => [#<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">,
|
||||
#<Grit::Blob "81d2c27608b352814cbe979a6acd678d30219678">,
|
||||
#<Grit::Tree "c3d07b0083f01a6e1ac969a0f32b8d06f20c62e5">,
|
||||
#<Grit::Tree "4d00fe177a8407dbbc64a24dbfc564762c0922d8">]
|
||||
|
||||
This tree contains two Blob objects and two Tree objects. The trees are
|
||||
subdirectories and the blobs are files. Trees below the root have additional
|
||||
attributes.
|
||||
|
||||
contents.last.name
|
||||
# => "lib"
|
||||
|
||||
contents.last.mode
|
||||
# => "040000"
|
||||
|
||||
There is a convenience method that allows you to get a named sub-object
|
||||
from a tree.
|
||||
|
||||
tree/"lib"
|
||||
# => #<Grit::Tree "e74893a3d8a25cbb1367cf241cc741bfd503c4b2">
|
||||
|
||||
You can also get a tree directly from the repo if you know its name.
|
||||
|
||||
repo.tree
|
||||
# => #<Grit::Tree "master">
|
||||
|
||||
repo.tree("91169e1f5fa4de2eaea3f176461f5dc784796769")
|
||||
# => #<Grit::Tree "91169e1f5fa4de2eaea3f176461f5dc784796769">
|
||||
|
||||
= The Blob object
|
||||
|
||||
A blob represents a file. Trees often contain blobs.
|
||||
|
||||
blob = tree.contents.first
|
||||
# => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
|
||||
|
||||
A blob has certain attributes.
|
||||
|
||||
blob.id
|
||||
# => "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666"
|
||||
|
||||
blob.name
|
||||
# => "README.txt"
|
||||
|
||||
blob.mode
|
||||
# => "100644"
|
||||
|
||||
blob.size
|
||||
# => 7726
|
||||
|
||||
You can get the data of a blob as a string.
|
||||
|
||||
blob.data
|
||||
# => "Grit is a library to ..."
|
||||
|
||||
You can also get a blob directly from the repo if you know its name.
|
||||
|
||||
repo.blob("4ebc8aea50e0a67e000ba29a30809d0a7b9b2666")
|
||||
# => #<Grit::Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
|
||||
|
||||
== LICENSE:
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2007 Tom Preston-Werner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,637 @@
|
|||
commit f8dd1f0b48e1106a62b47cc2927609ca589dc39a
|
||||
tree 4c23a5137714e62c52f22e99b3104122868400ab
|
||||
parent a0710955e70cbceef8cf805645a447f1b370b966
|
||||
parent b724247612be9f55df7914cb86b64703810d7b73
|
||||
author administrator <gmalamid@thoughtworks.com> 1224499981 +0100
|
||||
committer administrator <gmalamid@thoughtworks.com> 1224499981 +0100
|
||||
|
||||
imported William Morgans utilities too, which are very very nice
|
||||
|
||||
diff --cc git-publish-branch
|
||||
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b28b4fde621dff1c72bcb570183bbe923e4a24b2
|
||||
new file mode 100755
|
||||
--- /dev/null
|
||||
+++ b/git-publish-branch
|
||||
@@@ -1,0 -1,0 +1,70 @@@
|
||||
++#!/usr/bin/env ruby
|
||||
++
|
||||
++## git-publish-branch: a simple script to ease the unnecessarily complex
|
||||
++## task of "publishing" a branch, i.e., taking a local branch, creating a
|
||||
++## reference to it on a remote repo, and setting up the local branch to
|
||||
++## track the remote one, all in one go. you can even delete that remote
|
||||
++## reference.
|
||||
++##
|
||||
++## Usage: git publish-branch [-d] <branch> [repository]
|
||||
++##
|
||||
++## '-d' signifies deletion. <branch> is the branch to publish, and
|
||||
++## [repository] defaults to "origin". The remote branch name will be the
|
||||
++## same as the local branch name. Don't make life unnecessarily complex
|
||||
++## for yourself.
|
||||
++##
|
||||
++## Note that unpublishing a branch doesn't delete the local branch.
|
||||
++## Safety first!
|
||||
++##
|
||||
++## git-publish-branch Copyright 2008 William Morgan <wmorgan-git-wt-add@masanjin.net>.
|
||||
++## This program is free software: you can redistribute it and/or modify
|
||||
++## it under the terms of the GNU General Public License as published by
|
||||
++## the Free Software Foundation, either version 3 of the License, or (at
|
||||
++## your option) any later version.
|
||||
++##
|
||||
++## This program is distributed in the hope that it will be useful,
|
||||
++## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
++## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
++## GNU General Public License for more details.
|
||||
++##
|
||||
++## You can find the GNU General Public License at:
|
||||
++## http://www.gnu.org/licenses/
|
||||
++
|
||||
++def exec cmd
|
||||
++ puts cmd
|
||||
++ system cmd or die unless $fake
|
||||
++end
|
||||
++
|
||||
++def die s=nil
|
||||
++ $stderr.puts s if s
|
||||
++ exit(-1)
|
||||
++end
|
||||
++
|
||||
++head = `git symbolic-ref HEAD`.chomp.gsub(/refs\/heads\//, "")
|
||||
++delete = ARGV.delete "-d"
|
||||
++$fake = ARGV.delete "-n"
|
||||
++branch = (ARGV.shift || head).gsub(/refs\/heads\//, "")
|
||||
++remote = ARGV.shift || "origin"
|
||||
++local_ref = `git show-ref heads/#{branch}`
|
||||
++remote_ref = `git show-ref remotes/#{remote}/#{branch}`
|
||||
++remote_config = `git config branch.#{branch}.merge`
|
||||
++
|
||||
++if delete
|
||||
++ ## we don't do any checking here because the remote branch might actually
|
||||
++ ## exist, whether we actually know about it or not.
|
||||
++ exec "git push #{remote} :refs/heads/#{branch}"
|
||||
++
|
||||
++ unless local_ref.empty?
|
||||
++ exec "git config --unset branch.#{branch}.remote"
|
||||
++ exec "git config --unset branch.#{branch}.merge"
|
||||
++ end
|
||||
++else
|
||||
++ die "No local branch #{branch} exists!" if local_ref.empty?
|
||||
++ die "A remote branch #{branch} on #{remote} already exists!" unless remote_ref.empty?
|
||||
++ die "Local branch #{branch} is already a tracking branch!" unless remote_config.empty?
|
||||
++
|
||||
++ exec "git push #{remote} #{branch}:refs/heads/#{branch}"
|
||||
++ exec "git config branch.#{branch}.remote #{remote}"
|
||||
++ exec "git config branch.#{branch}.merge refs/heads/#{branch}"
|
||||
++end
|
||||
++
|
||||
diff --cc git-rank-contributors
|
||||
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3b272206d185e2f9b8089e6aaa00fde6acc308ef
|
||||
new file mode 100755
|
||||
--- /dev/null
|
||||
+++ b/git-rank-contributors
|
||||
@@@ -1,0 -1,0 +1,60 @@@
|
||||
++#!/usr/bin/env ruby
|
||||
++
|
||||
++## git-rank-contributors: a simple script to trace through the logs and
|
||||
++## rank contributors by the total size of the diffs they're responsible for.
|
||||
++## A change counts twice as much as a plain addition or deletion.
|
||||
++##
|
||||
++## Output may or may not be suitable for inclusion in a CREDITS file.
|
||||
++## Probably not without some editing, because people often commit from more
|
||||
++## than one address.
|
||||
++##
|
||||
++## git-rank-contributors Copyright 2008 William Morgan <wmorgan-git-wt-add@masanjin.net>.
|
||||
++## This program is free software: you can redistribute it and/or modify
|
||||
++## it under the terms of the GNU General Public License as published by
|
||||
++## the Free Software Foundation, either version 3 of the License, or (at
|
||||
++## your option) any later version.
|
||||
++##
|
||||
++## This program is distributed in the hope that it will be useful,
|
||||
++## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
++## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
++## GNU General Public License for more details.
|
||||
++##
|
||||
++## You can find the GNU General Public License at:
|
||||
++## http://www.gnu.org/licenses/
|
||||
++
|
||||
++class String
|
||||
++ def obfuscate; gsub(/@/, " at the ").gsub(/\.(\w+)(>|$)/, ' dot \1s\2') end
|
||||
++ def htmlize; gsub("&", "&").gsub("<", "<").gsub(">", ">") end
|
||||
++end
|
||||
++
|
||||
++lines = {}
|
||||
++verbose = ARGV.delete("-v")
|
||||
++obfuscate = ARGV.delete("-o")
|
||||
++htmlize = ARGV.delete("-h")
|
||||
++
|
||||
++author = nil
|
||||
++state = :pre_author
|
||||
++`git log -M -C -C -p --no-color`.each do |l|
|
||||
++ case
|
||||
++ when (state == :pre_author || state == :post_author) && l =~ /Author: (.*)$/
|
||||
++ author = $1
|
||||
++ state = :post_author
|
||||
++ lines[author] ||= 0
|
||||
++ when state == :post_author && l =~ /^\+\+\+/
|
||||
++ state = :in_diff
|
||||
++ when state == :in_diff && l =~ /^[\+\-]/
|
||||
++ lines[author] += 1
|
||||
++ when state == :in_diff && l =~ /^commit /
|
||||
++ state = :pre_author
|
||||
++ end
|
||||
++end
|
||||
++
|
||||
++lines.sort_by { |a, c| -c }.each do |a, c|
|
||||
++ a = a.obfuscate if obfuscate
|
||||
++ a = a.htmlize if htmlize
|
||||
++ if verbose
|
||||
++ puts "#{a}: #{c} lines of diff"
|
||||
++ else
|
||||
++ puts a
|
||||
++ end
|
||||
++end
|
||||
diff --cc git-show-merges
|
||||
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..12907502a6c6885e7183a0e71d9cfeed77917824
|
||||
new file mode 100755
|
||||
--- /dev/null
|
||||
+++ b/git-show-merges
|
||||
@@@ -1,0 -1,0 +1,49 @@@
|
||||
++#!/usr/bin/env ruby
|
||||
++
|
||||
++## git-show-merges: a simple script to show you which topic branches have
|
||||
++## been merged into the current branch, and which haven't. (Or, specify
|
||||
++## the set of merge branches you're interested in on the command line.)
|
||||
++##
|
||||
++## git-show-merges Copyright 2008 William Morgan <wmorgan-git-wt-add@masanjin.net>.
|
||||
++## This program is free software: you can redistribute it and/or modify
|
||||
++## it under the terms of the GNU General Public License as published by
|
||||
++## the Free Software Foundation, either version 3 of the License, or (at
|
||||
++## your option) any later version.
|
||||
++##
|
||||
++## This program is distributed in the hope that it will be useful,
|
||||
++## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
++## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
++## GNU General Public License for more details.
|
||||
++##
|
||||
++## You can find the GNU General Public License at:
|
||||
++## http://www.gnu.org/licenses/
|
||||
++heads = if ARGV.empty?
|
||||
++ [`git symbolic-ref HEAD`.chomp]
|
||||
++else
|
||||
++ ARGV
|
||||
++end.map { |r| r.gsub(/refs\/heads\//, "") }
|
||||
++
|
||||
++branches = `git show-ref --heads`.
|
||||
++ scan(/^\S+ refs\/heads\/(\S+)$/).
|
||||
++ map { |a| a.first }
|
||||
++
|
||||
++unknown = heads - branches
|
||||
++unless unknown.empty?
|
||||
++ $stderr.puts "Unknown branch: #{unknown.first}"
|
||||
++ exit(-1)
|
||||
++end
|
||||
++
|
||||
++branches -= heads
|
||||
++
|
||||
++heads.each do |h|
|
||||
++ merged = branches.select { |b| `git log #{h}..#{b}` == "" }
|
||||
++ unmerged = branches - merged
|
||||
++
|
||||
++ puts "merged into #{h}:"
|
||||
++ merged.each { |b| puts " #{b}" }
|
||||
++ puts
|
||||
++ puts "not merged into #{h}: "
|
||||
++ unmerged.each { |b| puts " #{b}" }
|
||||
++
|
||||
++ puts
|
||||
++end
|
||||
diff --cc git-wt-add
|
||||
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3125ab5495e5f2ab55ed48af5303031fae02c2ac
|
||||
new file mode 100755
|
||||
--- /dev/null
|
||||
+++ b/git-wt-add
|
||||
@@@ -1,0 -1,0 +1,196 @@@
|
||||
++#!/usr/bin/env ruby
|
||||
++
|
||||
++## git-wt-add: A darcs-style interactive staging script for git. As the
|
||||
++## name implies, git-wt-add walks you through unstaged changes on a
|
||||
++## hunk-by-hunk basis and allows you to pick the ones you'd like staged.
|
||||
++##
|
||||
++## git-wt-add Copyright 2007 William Morgan <wmorgan-git-wt-add@masanjin.net>.
|
||||
++## This program is free software: you can redistribute it and/or modify
|
||||
++## it under the terms of the GNU General Public License as published by
|
||||
++## the Free Software Foundation, either version 3 of the License, or
|
||||
++## (at your option) any later version.
|
||||
++##
|
||||
++## This program is distributed in the hope that it will be useful,
|
||||
++## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
++## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
++## GNU General Public License for more details.
|
||||
++##
|
||||
++## You can find the GNU General Public License at:
|
||||
++## http://www.gnu.org/licenses/
|
||||
++
|
||||
++COLOR = /\e\[\d*m/
|
||||
++
|
||||
++class Hunk
|
||||
++ attr_reader :file, :file_header, :diff
|
||||
++ attr_accessor :disposition
|
||||
++
|
||||
++ def initialize file, file_header, diff
|
||||
++ @file = file
|
||||
++ @file_header = file_header
|
||||
++ @diff = diff
|
||||
++ @disposition = :unknown
|
||||
++ end
|
||||
++
|
||||
++ def self.make_from diff
|
||||
++ ret = []
|
||||
++ state = :outside
|
||||
++ file_header = hunk = file = nil
|
||||
++
|
||||
++ diff.each do |l| # a little state machine to parse git diff output
|
||||
++ reprocess = false
|
||||
++ begin
|
||||
++ reprocess = false
|
||||
++ case
|
||||
++ when state == :outside && l =~ /^(#{COLOR})*diff --git a\/(.+) b\/(\2)/
|
||||
++ file = $2
|
||||
++ file_header = ""
|
||||
++ when state == :outside && l =~ /^(#{COLOR})*index /
|
||||
++ when state == :outside && l =~ /^(#{COLOR})*(---|\+\+\+) /
|
||||
++ file_header += l + "\n"
|
||||
++ when state == :outside && l =~ /^(#{COLOR})*@@ /
|
||||
++ state = :in_hunk
|
||||
++ hunk = l + "\n"
|
||||
++ when state == :in_hunk && l =~ /^(#{COLOR})*(@@ |diff --git a)/
|
||||
++ ret << Hunk.new(file, file_header, hunk)
|
||||
++ state = :outside
|
||||
++ reprocess = true
|
||||
++ when state == :in_hunk
|
||||
++ hunk += l + "\n"
|
||||
++ else
|
||||
++ raise "unparsable diff input: #{l.inspect}"
|
||||
++ end
|
||||
++ end while reprocess
|
||||
++ end
|
||||
++
|
||||
++ ## add the final hunk
|
||||
++ ret << Hunk.new(file, file_header, hunk) if hunk
|
||||
++
|
||||
++ ret
|
||||
++ end
|
||||
++end
|
||||
++
|
||||
++def help
|
||||
++ puts <<EOS
|
||||
++y: record this patch
|
||||
++n: don't record it
|
||||
++w: wait and decide later, defaulting to no
|
||||
++
|
||||
++s: don't record the rest of the changes to this file
|
||||
++f: record the rest of the changes to this file
|
||||
++
|
||||
++d: record selected patches, skipping all the remaining patches
|
||||
++a: record all the remaining patches
|
||||
++q: cancel record
|
||||
++
|
||||
++j: skip to next patch
|
||||
++k: back up to previous patch
|
||||
++c: calculate number of patches
|
||||
++h or ?: show this help
|
||||
++
|
||||
++<Space>: accept the current default (which is capitalized)
|
||||
++EOS
|
||||
++end
|
||||
++
|
||||
++def walk_through hunks
|
||||
++ skip_files, record_files = {}, {}
|
||||
++ skip_rest = record_rest = false
|
||||
++
|
||||
++ while hunks.any? { |h| h.disposition == :unknown }
|
||||
++ pos = 0
|
||||
++ until pos >= hunks.length
|
||||
++ h = hunks[pos]
|
||||
++ if h.disposition != :unknown
|
||||
++ pos += 1
|
||||
++ next
|
||||
++ elsif skip_rest || skip_files[h.file]
|
||||
++ h.disposition = :ignore
|
||||
++ pos += 1
|
||||
++ next
|
||||
++ elsif record_rest || record_files[h.file]
|
||||
++ h.disposition = :record
|
||||
++ pos += 1
|
||||
++ next
|
||||
++ end
|
||||
++
|
||||
++ puts "Hunk from #{h.file}"
|
||||
++ puts h.diff
|
||||
++ print "Shall I stage this change? (#{pos + 1}/#{hunks.length}) [ynWsfqadk], or ? for help: "
|
||||
++ c = $stdin.getc
|
||||
++ puts
|
||||
++ case c
|
||||
++ when ?y: h.disposition = :record
|
||||
++ when ?n: h.disposition = :ignore
|
||||
++ when ?w, ?\ : h.disposition = :unknown
|
||||
++ when ?s
|
||||
++ h.disposition = :ignore
|
||||
++ skip_files[h.file] = true
|
||||
++ when ?f
|
||||
++ h.disposition = :record
|
||||
++ record_files[h.file] = true
|
||||
++ when ?d: skip_rest = true
|
||||
++ when ?a: record_rest = true
|
||||
++ when ?q: exit
|
||||
++ when ?k
|
||||
++ if pos > 0
|
||||
++ hunks[pos - 1].disposition = :unknown
|
||||
++ pos -= 2 # double-bah
|
||||
++ end
|
||||
++ else
|
||||
++ help
|
||||
++ pos -= 1 # bah
|
||||
++ end
|
||||
++
|
||||
++ pos += 1
|
||||
++ puts
|
||||
++ end
|
||||
++ end
|
||||
++end
|
||||
++
|
||||
++def make_patch hunks
|
||||
++ patch = ""
|
||||
++ did_header = {}
|
||||
++ hunks.each do |h|
|
||||
++ next unless h.disposition == :record
|
||||
++ unless did_header[h.file]
|
||||
++ patch += h.file_header
|
||||
++ did_header[h.file] = true
|
||||
++ end
|
||||
++ patch += h.diff
|
||||
++ end
|
||||
++
|
||||
++ patch.gsub COLOR, ""
|
||||
++end
|
||||
++
|
||||
++### execution starts here ###
|
||||
++
|
||||
++diff = `git diff`.split(/\r?\n/)
|
||||
++if diff.empty?
|
||||
++ puts "No unstaged changes."
|
||||
++ exit
|
||||
++end
|
||||
++hunks = Hunk.make_from diff
|
||||
++
|
||||
++## unix-centric!
|
||||
++state = `stty -g`
|
||||
++begin
|
||||
++ `stty -icanon` # immediate keypress mode
|
||||
++ walk_through hunks
|
||||
++ensure
|
||||
++ `stty #{state}`
|
||||
++end
|
||||
++
|
||||
++patch = make_patch hunks
|
||||
++if patch.empty?
|
||||
++ puts "No changes selected for staging."
|
||||
++else
|
||||
++ IO.popen("git apply --cached", "w") { |f| f.puts patch }
|
||||
++ puts <<EOS
|
||||
++Staged patch of #{patch.split("\n").size} lines.
|
||||
++
|
||||
++Possible next commands:
|
||||
++ git diff --cached: see staged changes
|
||||
++ git commit: commit staged changes
|
||||
++ git reset: unstage changes
|
||||
++EOS
|
||||
++end
|
||||
++
|
||||
diff --cc git-wtf
|
||||
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ea4b27f6812cf9daf84b047bff4443cc554f92bf
|
||||
new file mode 100755
|
||||
--- /dev/null
|
||||
+++ b/git-wtf
|
||||
@@@ -1,0 -1,0 +1,223 @@@
|
||||
++#!/usr/bin/env ruby
|
||||
++
|
||||
++## git-wtf: display the state of your repository in a readable and easy-to-scan
|
||||
++## format.
|
||||
++##
|
||||
++## git-wtf tries to ease the task of having many git branches. It's also useful
|
||||
++## for getting a summary of how tracking branches relate to a remote server.
|
||||
++##
|
||||
++## git-wtf shows you:
|
||||
++## - How your branch relates to the remote repo, if it's a tracking branch.
|
||||
++## - How your branch relates to non-feature ("version") branches, if it's a
|
||||
++## feature branch.
|
||||
++## - How your branch relates to the feature branches, if it's a version branch.
|
||||
++##
|
||||
++## For each of these relationships, git-wtf displays the commits pending on
|
||||
++## either side, if any. It displays checkboxes along the side for easy scanning
|
||||
++## of merged/non-merged branches.
|
||||
++##
|
||||
++## If you're working against a remote repo, git-wtf is best used between a 'git
|
||||
++## fetch' and a 'git merge' (or 'git pull' if you don't mind the redundant
|
||||
++## network access).
|
||||
++##
|
||||
++## Usage: git wtf [branch+] [-l|--long] [-a|--all] [--dump-config]
|
||||
++##
|
||||
++## If [branch] is not specified, git-wtf will use the current branch. With
|
||||
++## --long, you'll see author info and date for each commit. With --all, you'll
|
||||
++## see all commits, not just the first 5. With --dump-config, git-wtf will
|
||||
++## print out its current configuration in YAML format and exit.
|
||||
++##
|
||||
++## git-wtf uses some heuristics to determine which branches are version
|
||||
++## branches, and which are feature branches. (Specifically, it assumes the
|
||||
++## version branches are named "master", "next" and "edge".) If it guesses
|
||||
++## incorrectly, you will have to create a .git-wtfrc file.
|
||||
++##
|
||||
++## git-wtf looks for a .git-wtfrc file starting in the current directory, and
|
||||
++## recursively up to the root. The config file is a YAML file that specifies
|
||||
++## the version branches, any branches to ignore, and the max number of commits
|
||||
++## to display when --all isn't used. To start building a configuration file,
|
||||
++## run "git-wtf --dump-config > .git-wtfrc" and edit it.
|
||||
++##
|
||||
++## IMPORTANT NOTE: all local branches referenced in .git-wtfrc must be prefixed
|
||||
++## with heads/, e.g. "heads/master". Remote branches must be of the form
|
||||
++## remotes/<remote>/<branch>.
|
||||
++##
|
||||
++## git-wtf Copyright 2008 William Morgan <wmorgan-git-wt-add@masanjin.net>.
|
||||
++## This program is free software: you can redistribute it and/or modify it
|
||||
++## under the terms of the GNU General Public License as published by the Free
|
||||
++## Software Foundation, either version 3 of the License, or (at your option)
|
||||
++## any later version.
|
||||
++##
|
||||
++## This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
++## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
++## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
++## more details.
|
||||
++##
|
||||
++## You can find the GNU General Public License at: http://www.gnu.org/licenses/
|
||||
++
|
||||
++
|
||||
++require 'yaml'
|
||||
++CONFIG_FN = ".git-wtfrc"
|
||||
++
|
||||
++class Numeric; def pluralize s; "#{to_s} #{s}" + (self != 1 ? "s" : "") end end
|
||||
++
|
||||
++$long = ARGV.delete("--long") || ARGV.delete("-l")
|
||||
++$all = ARGV.delete("--all") || ARGV.delete("-a")
|
||||
++$dump_config = ARGV.delete("--dump-config")
|
||||
++
|
||||
++## find config file
|
||||
++$config = { "versions" => %w(heads/master heads/next heads/edge), "ignore" => [], "max_commits" => 5 }.merge begin
|
||||
++ p = File.expand_path "."
|
||||
++ fn = while true
|
||||
++ fn = File.join p, CONFIG_FN
|
||||
++ break fn if File.exist? fn
|
||||
++ pp = File.expand_path File.join(p, "..")
|
||||
++ break if p == pp
|
||||
++ p = pp
|
||||
++ end
|
||||
++
|
||||
++ (fn && YAML::load_file(fn)) || {} # YAML turns empty files into false
|
||||
++end
|
||||
++
|
||||
++if $dump_config
|
||||
++ puts $config.to_yaml
|
||||
++ exit(0)
|
||||
++end
|
||||
++
|
||||
++## the set of commits in 'to' that aren't in 'from'.
|
||||
++## if empty, 'to' has been merged into 'from'.
|
||||
++def commits_between from, to
|
||||
++ if $long
|
||||
++ `git log --pretty=format:"- %s [%h] (%ae; %ar)" #{from}..#{to}`
|
||||
++ else
|
||||
++ `git log --pretty=format:"- %s [%h]" #{from}..#{to}`
|
||||
++ end.split(/[\r\n]+/)
|
||||
++end
|
||||
++
|
||||
++def show_commits commits, prefix=" "
|
||||
++ if commits.empty?
|
||||
++ puts "#{prefix} none"
|
||||
++ else
|
||||
++ max = $all ? commits.size : $config["max_commits"]
|
||||
++ max -= 1 if max == commits.size - 1 # never show "and 1 more"
|
||||
++ commits[0 ... max].each { |c| puts "#{prefix}#{c}" }
|
||||
++ puts "#{prefix}... and #{commits.size - max} more." if commits.size > max
|
||||
++ end
|
||||
++end
|
||||
++
|
||||
++def ahead_behind_string ahead, behind
|
||||
++ [ahead.empty? ? nil : "#{ahead.size.pluralize 'commit'} ahead",
|
||||
++ behind.empty? ? nil : "#{behind.size.pluralize 'commit'} behind"].
|
||||
++ compact.join("; ")
|
||||
++end
|
||||
++
|
||||
++def show b, all_branches
|
||||
++ puts "Local branch: #{b[:local_branch]}"
|
||||
++ both = false
|
||||
++
|
||||
++ if b[:remote_branch]
|
||||
++ pushc = commits_between b[:remote_branch], b[:local_branch]
|
||||
++ pullc = commits_between b[:local_branch], b[:remote_branch]
|
||||
++
|
||||
++ both = !pushc.empty? && !pullc.empty?
|
||||
++ if pushc.empty?
|
||||
++ puts "[x] in sync with remote"
|
||||
++ else
|
||||
++ action = both ? "push after rebase / merge" : "push"
|
||||
++ puts "[ ] NOT in sync with remote (needs #{action})"
|
||||
++ show_commits pushc
|
||||
++ end
|
||||
++
|
||||
++ puts "\nRemote branch: #{b[:remote_branch]} (#{b[:remote_url]})"
|
||||
++
|
||||
++ if pullc.empty?
|
||||
++ puts "[x] in sync with local"
|
||||
++ else
|
||||
++ action = pushc.empty? ? "merge" : "rebase / merge"
|
||||
++ puts "[ ] NOT in sync with local (needs #{action})"
|
||||
++ show_commits pullc
|
||||
++
|
||||
++ both = !pushc.empty? && !pullc.empty?
|
||||
++ end
|
||||
++ end
|
||||
++
|
||||
++ vbs, fbs = all_branches.partition { |name, br| $config["versions"].include? br[:local_branch] }
|
||||
++ if $config["versions"].include? b[:local_branch]
|
||||
++ puts "\nFeature branches:" unless fbs.empty?
|
||||
++ fbs.each do |name, br|
|
||||
++ remote_ahead = b[:remote_branch] ? commits_between(b[:remote_branch], br[:local_branch]) : []
|
||||
++ local_ahead = commits_between b[:local_branch], br[:local_branch]
|
||||
++ if local_ahead.empty? && remote_ahead.empty?
|
||||
++ puts "[x] #{br[:name]} is merged in"
|
||||
++ elsif local_ahead.empty? && b[:remote_branch]
|
||||
++ puts "(x) #{br[:name]} merged in (only locally)"
|
||||
++ else
|
||||
++ behind = commits_between br[:local_branch], b[:local_branch]
|
||||
++ puts "[ ] #{br[:name]} is NOT merged in (#{ahead_behind_string local_ahead, behind})"
|
||||
++ show_commits local_ahead
|
||||
++ end
|
||||
++ end
|
||||
++ else
|
||||
++ puts "\nVersion branches:" unless vbs.empty? # unlikely
|
||||
++ vbs.each do |v, br|
|
||||
++ ahead = commits_between v, b[:local_branch]
|
||||
++ if ahead.empty?
|
||||
++ puts "[x] merged into #{v}"
|
||||
++ else
|
||||
++ #behind = commits_between b[:local_branch], v
|
||||
++ puts "[ ] NOT merged into #{v} (#{ahead.size.pluralize 'commit'} ahead)"
|
||||
++ show_commits ahead
|
||||
++ end
|
||||
++ end
|
||||
++ end
|
||||
++
|
||||
++ puts "\nWARNING: local and remote branches have diverged. A merge will occur unless you rebase." if both
|
||||
++end
|
||||
++
|
||||
++branches = `git show-ref`.inject({}) do |hash, l|
|
||||
++ sha1, ref = l.chomp.split " refs/"
|
||||
++ next hash if $config["ignore"].member? ref
|
||||
++ next hash unless ref =~ /^heads\/(.+)/
|
||||
++ name = $1
|
||||
++ hash[name] = { :name => name, :local_branch => ref }
|
||||
++ hash
|
||||
++end
|
||||
++
|
||||
++remotes = `git config --get-regexp ^remote\.\*\.url`.inject({}) do |hash, l|
|
||||
++ l =~ /^remote\.(.+?)\.url (.+)$/ or next hash
|
||||
++ hash[$1] ||= $2
|
||||
++ hash
|
||||
++end
|
||||
++
|
||||
++`git config --get-regexp ^branch\.`.each do |l|
|
||||
++ case l
|
||||
++ when /branch\.(.*?)\.remote (.+)/
|
||||
++ branches[$1] ||= {}
|
||||
++ branches[$1][:remote] = $2
|
||||
++ branches[$1][:remote_url] = remotes[$2]
|
||||
++ when /branch\.(.*?)\.merge ((refs\/)?heads\/)?(.+)/
|
||||
++ branches[$1] ||= {}
|
||||
++ branches[$1][:remote_mergepoint] = $4
|
||||
++ end
|
||||
++end
|
||||
++
|
||||
++branches.each { |k, v| v[:remote_branch] = "#{v[:remote]}/#{v[:remote_mergepoint]}" if v[:remote] && v[:remote_mergepoint] }
|
||||
++
|
||||
++show_dirty = ARGV.empty?
|
||||
++targets = if ARGV.empty?
|
||||
++ [`git symbolic-ref HEAD`.chomp.sub(/^refs\/heads\//, "")]
|
||||
++else
|
||||
++ ARGV
|
||||
++end.map { |t| branches[t] or abort "Error: can't find branch #{t.inspect}." }
|
||||
++
|
||||
++targets.each { |t| show t, branches }
|
||||
++
|
||||
++modified = show_dirty && `git ls-files -m` != ""
|
||||
++uncommitted = show_dirty && `git diff-index --cached HEAD` != ""
|
||||
++
|
||||
++puts if modified || uncommitted
|
||||
++puts "NOTE: working directory contains modified files" if modified
|
||||
++puts "NOTE: staging area contains staged but uncommitted files" if uncommitted
|
||||
++
|
||||
++# the end!
|
||||
++
|
Загрузка…
Ссылка в новой задаче