├── LICENSE
├── README.md
└── git-vanity-sha
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | GLWT Public License
3 | Copyright (c) 2018 Matt Baker
4 |
5 | The author has no f**king clue what the code in this project does.
6 | It might just work or not, there is no third option.
7 |
8 | Everyone is permitted to copy, distribute, modify, merge, sell, publish,
9 | sublicense or whatever you want with this software but at your OWN RISK.
10 |
11 |
12 | GOOD LUCK WITH THAT PUBLIC LICENSE
13 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION, AND MODIFICATION
14 |
15 | 0. You just DO WHAT THE F*CK YOU WANT TO as long as you NEVER LEAVE A
16 | TRACE TO TRACK THE AUTHOR of the original product.
17 |
18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
19 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 | DEALINGS IN THE SOFTWARE.
22 |
23 | Good luck and Godspeed.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # git vanity-sha
2 |
3 | This is a Very Good Program inspired by this [tweet](https://mobile.twitter.com/leinweber/status/989415433605283840).
4 |
5 |
6 |
7 |
8 |
9 | He wasn't joking.
10 |
11 |
12 |
13 |
14 |
15 | So I thought maybe I'd just write a program to do it.
16 |
17 | `git vanity-sha` will try its darndest to tweak the commiter timestamp of your last commit to produce a commit SHA using the hexadecimal prefix you supply.
18 |
19 | ```plaintext
20 | $ git commit -am "refactor warp core"
21 | [master 909939a] refactor warp core
22 | 1 file changed, 12 insertions(+), 8 deletions(-)
23 |
24 | $ git vanity-sha cafe
25 | Searching for new SHA...
26 |
27 | SHA found: cafe7f7fe2054aa79dd6f5e1f994242b70cd7572
28 | Change committer timestamp to 2018-04-27 00:31:18 -0700? This will amend your commit.
29 | (y/n): y
30 |
31 | -----------------------------------------------
32 | commit cafe7f7fe2054aa79dd6f5e1f994242b70cd7572
33 | Author: Matt Baker
34 |
35 | refactor warp core
36 | ```
37 |
38 | Now you can amend a commit to have a quirky prefix whenever you want except for when `git-vanity-sha` doesn't find one.
39 |
40 | ## Installation
41 |
42 | Grab the `git-vanity-sha` script and stick it in your path somewhere. Make sure you `chmod +x` it, and `hash -r`.
43 |
44 | Now you can say `git vanity-sha beef` in your repo.
45 |
46 | ## Frequently Asked Questions
47 |
48 | ### How does it work?
49 |
50 | `git vanity-sha` will attempt to find a commit SHA starting with the hex prefix you specify by applying a delta to the committer timestamp of your last commit. It starts off making small changes to the timestamp (a few seconds) and gets bigger as it searches (up to several days).
51 |
52 | If it finds a timestamp that will cause your commit's SHA to have the target prefix, it will give you the option to amend that commit or abort the process.
53 |
54 | ### Is this a good idea?
55 |
56 | Absolutely not.
57 |
58 | ### Will this mess something up?
59 |
60 | Probably.
61 |
62 | ### Will you help me if something goes wrong?
63 |
64 | Oh god no.
65 |
66 | ### It didn't find a SHA with the prefix I wanted :(
67 |
68 | If you're really determined, then change `TIMESTAMP_DELTA_MAX` to a huge number and go for a walk and maybe you'll get lucky.
69 |
70 | ### It doesn't work, the hash doesn't have the proper prefix!
71 |
72 | Do you have commit signing enabled? You need to disable it, otherwise it won't work due to git limitations.
73 |
--------------------------------------------------------------------------------
/git-vanity-sha:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'digest'
3 |
4 | module VanitySha
5 | extend self
6 |
7 | COMMITTER_PATTERN = /^committer .* \<.*\> (?\d+)(?.*$)/
8 |
9 | TIMESTAMP_DELTA_MAX = 10 * 24 * 60 * 60
10 |
11 | DELTAS = Enumerator.new do |enumerator|
12 | for i in 0..TIMESTAMP_DELTA_MAX
13 | enumerator << i
14 | enumerator << -i
15 | end
16 | end
17 |
18 | def get_commit_info()
19 | `git cat-file commit HEAD`
20 | end
21 |
22 | def extract_committer(commit_info)
23 | committer = commit_info
24 | .split("\n")
25 | .map {|line| line.match(COMMITTER_PATTERN)}
26 | .compact
27 | .first
28 |
29 | [committer.string, committer[:timestamp].to_i, committer[:timezone]]
30 | end
31 |
32 | def search(commit_info, hex_prefix)
33 | committer_line, commit_ts = extract_committer(commit_info)
34 |
35 | DELTAS.each do |delta|
36 | new_committer_line = committer_line.sub(commit_ts.to_s, (commit_ts + delta).to_s)
37 | new_commit = commit_info.sub(committer_line, new_committer_line)
38 | new_sha = get_sha(new_commit)
39 | return [delta, new_sha] if new_sha.start_with?(hex_prefix)
40 | end
41 | nil
42 | end
43 |
44 | def get_sha(commit_info)
45 | Digest::SHA1.hexdigest "#{commit_header(commit_info)}#{commit_info}"
46 | end
47 |
48 | def amend_commit(new_ts, original_tz)
49 | `LC_ALL=C GIT_COMMITTER_DATE=\"#{new_ts}#{original_tz}\" git commit --allow-empty --amend --no-edit`
50 | end
51 |
52 | def commit_header(commit_info)
53 | "commit #{commit_info.length}\0"
54 | end
55 | end
56 |
57 | if ARGV.length != 1 || ARGV[0].length < 1
58 | puts "usage: git vanity-sha prefix"
59 | puts "example: git vanity-sha CAFE"
60 | exit(1)
61 | end
62 |
63 | target_prefix = ARGV[0].downcase
64 | original_commit_info = VanitySha.get_commit_info()
65 | _, original_ts, original_tz = VanitySha.extract_committer(original_commit_info)
66 |
67 | puts "Searching for new SHA...\n"
68 |
69 | result = VanitySha.search(original_commit_info, target_prefix)
70 |
71 | if result
72 | delta, sha = result
73 | new_ts = original_ts + delta
74 |
75 | puts "SHA found: #{sha.sub(target_prefix, "\e[32m#{target_prefix}\e[0m")}"
76 | puts "Change committer timestamp to #{Time.at(new_ts)}? This will amend your commit."
77 | print "(y/n): "
78 |
79 | if STDIN.gets.chomp == "y"
80 | VanitySha.amend_commit(new_ts, original_tz)
81 | puts "\n" + "-" * 47
82 | puts `git show --quiet --format=short HEAD`
83 | else
84 | puts "Aborting."
85 | end
86 | else
87 | puts "Failed to generate a sha with prefix #{target_prefix}."
88 | end
89 |
--------------------------------------------------------------------------------