git-alias 1.2.30

A fast git alias tool with dual-style command support
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
use colored::Colorize;
use std::collections::HashMap;

pub fn get_builtin_aliases() -> HashMap<String, Vec<String>> {
    let mut aliases = HashMap::new();

    // add
    aliases.insert("a".to_string(), vec!["add".to_string()]);
    aliases.insert("ga".to_string(), vec!["add".to_string()]);
    aliases.insert("aa".to_string(), vec!["add".to_string(), ".".to_string()]);
    aliases.insert("gaa".to_string(), vec!["add".to_string(), ".".to_string()]);

    // status
    aliases.insert("s".to_string(), vec!["status".to_string()]);
    aliases.insert("gs".to_string(), vec!["status".to_string()]);
    aliases.insert("ss".to_string(), vec!["status".to_string(), "-s".to_string()]);
    aliases.insert("gss".to_string(), vec!["status".to_string(), "-s".to_string()]);
    aliases
        .insert("sb".to_string(), vec!["status".to_string(), "-s".to_string(), "-b".to_string()]);
    aliases
        .insert("gsb".to_string(), vec!["status".to_string(), "-s".to_string(), "-b".to_string()]);

    // commit
    aliases.insert("cm".to_string(), vec!["commit".to_string()]);
    aliases.insert("gcm".to_string(), vec!["commit".to_string()]);
    aliases.insert("cma".to_string(), vec!["commit".to_string(), "--amend".to_string()]);
    aliases.insert("gcma".to_string(), vec!["commit".to_string(), "--amend".to_string()]);
    aliases.insert(
        "cmn".to_string(),
        vec!["commit".to_string(), "--no-edit".to_string(), "--amend".to_string()],
    );
    aliases.insert(
        "gcmn".to_string(),
        vec!["commit".to_string(), "--no-edit".to_string(), "--amend".to_string()],
    );
    aliases.insert("cmm".to_string(), vec!["commit".to_string(), "-m".to_string()]);
    aliases.insert("gcmm".to_string(), vec!["commit".to_string(), "-m".to_string()]);
    aliases.insert("gcmai".to_string(), vec!["cmai".to_string()]);
    aliases.insert("cmai".to_string(), vec!["cmai".to_string()]);

    // push
    aliases.insert("p".to_string(), vec!["pull".to_string()]);
    aliases.insert("ps".to_string(), vec!["push".to_string()]);
    aliases.insert("gp".to_string(), vec!["pull".to_string()]);
    aliases.insert("gps".to_string(), vec!["push".to_string()]);
    aliases.insert("psf".to_string(), vec!["push".to_string(), "--force-with-lease".to_string()]);
    aliases.insert("gpsf".to_string(), vec!["push".to_string(), "--force-with-lease".to_string()]);
    aliases.insert(
        "psu".to_string(),
        vec!["push".to_string(), "-u".to_string(), "origin".to_string(), "HEAD".to_string()],
    );
    aliases.insert(
        "gpsu".to_string(),
        vec!["push".to_string(), "-u".to_string(), "origin".to_string(), "HEAD".to_string()],
    );

    // pull
    aliases.insert("pl".to_string(), vec!["pull".to_string()]);
    aliases.insert("gpl".to_string(), vec!["pull".to_string()]);
    aliases
        .insert("pla".to_string(), vec!["pull".to_string(), "--all".to_string(), "-t".to_string()]);
    aliases.insert(
        "gpla".to_string(),
        vec!["pull".to_string(), "--all".to_string(), "-t".to_string()],
    );

    // branch
    aliases.insert("b".to_string(), vec!["branch".to_string()]);
    aliases.insert("gb".to_string(), vec!["branch".to_string()]);
    aliases.insert("ba".to_string(), vec!["branch".to_string(), "--all".to_string()]);
    aliases.insert("gba".to_string(), vec!["branch".to_string(), "--all".to_string()]);
    aliases.insert("bra".to_string(), vec!["branch".to_string(), "-avv".to_string()]);
    aliases.insert("gbra".to_string(), vec!["branch".to_string(), "-avv".to_string()]);
    aliases.insert("bv".to_string(), vec!["branch".to_string(), "-vv".to_string()]);
    aliases.insert("gbv".to_string(), vec!["branch".to_string(), "-vv".to_string()]);
    aliases.insert("bc".to_string(), vec!["branch".to_string(), "--contains".to_string()]);
    aliases.insert("gbc".to_string(), vec!["branch".to_string(), "--contains".to_string()]);
    aliases.insert(
        "bcr".to_string(),
        vec!["branch".to_string(), "-r".to_string(), "--contains".to_string()],
    );
    aliases.insert(
        "gbcr".to_string(),
        vec!["branch".to_string(), "-r".to_string(), "--contains".to_string()],
    );
    aliases.insert("bd".to_string(), vec!["branch".to_string(), "--delete".to_string()]);
    aliases.insert("gbd".to_string(), vec!["branch".to_string(), "-d".to_string()]);
    aliases.insert(
        "gbD".to_string(),
        vec!["branch".to_string(), "--delete".to_string(), "--force".to_string()],
    );

    // checkout
    aliases.insert("ck".to_string(), vec!["checkout".to_string()]);
    aliases.insert("gck".to_string(), vec!["checkout".to_string()]);
    aliases.insert("ckb".to_string(), vec!["checkout".to_string(), "-b".to_string()]);
    aliases.insert("gckb".to_string(), vec!["checkout".to_string(), "-b".to_string()]);

    // switch
    aliases.insert("sw".to_string(), vec!["switch".to_string()]);
    aliases.insert("gsw".to_string(), vec!["switch".to_string()]);
    aliases.insert("swc".to_string(), vec!["switch".to_string(), "--create".to_string()]);
    aliases.insert("gswc".to_string(), vec!["switch".to_string(), "--create".to_string()]);
    aliases.insert("swd".to_string(), vec!["switch".to_string(), "--detach".to_string()]);
    aliases.insert("gswd".to_string(), vec!["switch".to_string(), "--detach".to_string()]);
    aliases.insert("swf".to_string(), vec!["switch".to_string(), "--force".to_string()]);
    aliases.insert("gswf".to_string(), vec!["switch".to_string(), "--force".to_string()]);

    // log
    let log_format = vec![
        "log".to_string(),
        "--color".to_string(),
        "--graph".to_string(),
        "--format=%Cred%h%Creset -%C(yellow)%d %Cblue%s %Cgreen(%ci) %C(bold blue)<%an>%Creset"
            .to_string(),
        "--abbrev=8".to_string(),
    ];

    aliases.insert("l".to_string(), log_format.clone());
    aliases.insert("gl".to_string(), log_format.clone());
    aliases.insert("lg".to_string(), vec!["log".to_string(), "-S".to_string()]);
    aliases.insert("glg".to_string(), vec!["log".to_string(), "-S".to_string()]);
    aliases.insert("lgg".to_string(), vec!["log".to_string(), "-G".to_string()]);
    aliases.insert("glgg".to_string(), vec!["log".to_string(), "-G".to_string()]);

    let mut ls_format = log_format.clone();
    ls_format.push("--no-merges".to_string());
    aliases.insert("ls".to_string(), ls_format.clone());
    aliases.insert("gls".to_string(), ls_format.clone());

    let mut lss_format = ls_format.clone();
    lss_format.push("--stat=200".to_string());
    aliases.insert("lss".to_string(), lss_format.clone());
    aliases.insert("glss".to_string(), lss_format.clone());

    // log with patch
    aliases
        .insert("lp".to_string(), vec!["log".to_string(), "--color".to_string(), "-p".to_string()]);
    aliases.insert(
        "glp".to_string(),
        vec!["log".to_string(), "--color".to_string(), "-p".to_string()],
    );

    // diff
    aliases.insert("d".to_string(), vec!["diff".to_string()]);
    aliases.insert("gd".to_string(), vec!["diff".to_string()]);
    aliases.insert("di".to_string(), vec!["diff".to_string()]);
    aliases.insert("gdi".to_string(), vec!["diff".to_string()]);
    aliases.insert("dc".to_string(), vec!["diff".to_string(), "--cached".to_string()]);
    aliases.insert("gdc".to_string(), vec!["diff".to_string(), "--cached".to_string()]);
    aliases.insert("ds".to_string(), vec!["diff".to_string(), "--stat=200".to_string()]);
    aliases.insert("gds".to_string(), vec!["diff".to_string(), "--stat=200".to_string()]);
    aliases.insert("dw".to_string(), vec!["diff".to_string(), "--word-diff".to_string()]);
    aliases.insert("gdw".to_string(), vec!["diff".to_string(), "--word-diff".to_string()]);

    // reset
    aliases.insert("rsh".to_string(), vec!["reset".to_string(), "--hard".to_string()]);
    aliases.insert("grsh".to_string(), vec!["reset".to_string(), "--hard".to_string()]);
    aliases.insert("rs".to_string(), vec!["reset".to_string()]);
    aliases.insert("grs".to_string(), vec!["reset".to_string()]);
    aliases.insert("rss".to_string(), vec!["reset".to_string(), "--soft".to_string()]);
    aliases.insert("grss".to_string(), vec!["reset".to_string(), "--soft".to_string()]);
    aliases.insert("uns".to_string(), vec!["restore".to_string(), "--staged".to_string()]);
    aliases.insert("guns".to_string(), vec!["restore".to_string(), "--staged".to_string()]);
    aliases.insert("un".to_string(), vec!["restore".to_string()]);
    aliases.insert("gun".to_string(), vec!["restore".to_string()]);

    // revert
    aliases.insert("rvr".to_string(), vec!["revert".to_string()]);
    aliases.insert("grvr".to_string(), vec!["revert".to_string()]);

    // stash
    aliases.insert("st".to_string(), vec!["stash".to_string()]);
    aliases.insert("gst".to_string(), vec!["stash".to_string()]);
    aliases.insert("stp".to_string(), vec!["stash".to_string(), "pop".to_string()]);
    aliases.insert("gstp".to_string(), vec!["stash".to_string(), "pop".to_string()]);
    aliases.insert("sta".to_string(), vec!["stash".to_string(), "apply".to_string()]);
    aliases.insert("gsta".to_string(), vec!["stash".to_string(), "apply".to_string()]);
    aliases.insert("stl".to_string(), vec!["stash".to_string(), "list".to_string()]);
    aliases.insert("gstl".to_string(), vec!["stash".to_string(), "list".to_string()]);
    aliases.insert("std".to_string(), vec!["stash".to_string(), "drop".to_string()]);
    aliases.insert("gstd".to_string(), vec!["stash".to_string(), "drop".to_string()]);

    // remote
    aliases.insert("r".to_string(), vec!["remote".to_string()]);
    aliases.insert("gr".to_string(), vec!["remote".to_string()]);
    aliases.insert("rv".to_string(), vec!["remote".to_string(), "-v".to_string()]);
    aliases.insert("grv".to_string(), vec!["remote".to_string(), "-v".to_string()]);
    aliases.insert("ra".to_string(), vec!["remote".to_string(), "add".to_string()]);
    aliases.insert("gra".to_string(), vec!["remote".to_string(), "add".to_string()]);
    aliases.insert("rd".to_string(), vec!["remote".to_string(), "remove".to_string()]);
    aliases.insert("grd".to_string(), vec!["remote".to_string(), "remove".to_string()]);

    // fetch
    aliases.insert("f".to_string(), vec!["fetch".to_string()]);
    aliases.insert("gf".to_string(), vec!["fetch".to_string()]);
    aliases.insert(
        "fa".to_string(),
        vec!["fetch".to_string(), "--all".to_string(), "--prune".to_string()],
    );
    aliases.insert(
        "gfa".to_string(),
        vec!["fetch".to_string(), "--all".to_string(), "--prune".to_string()],
    );

    // merge
    aliases.insert("m".to_string(), vec!["merge".to_string()]);
    aliases.insert("gm".to_string(), vec!["merge".to_string()]);
    aliases.insert("mf".to_string(), vec!["merge".to_string(), "--ff-only".to_string()]);
    aliases.insert("gmf".to_string(), vec!["merge".to_string(), "--ff-only".to_string()]);
    aliases.insert("mo".to_string(), vec!["merge".to_string(), "-Xtheirs".to_string()]);
    aliases.insert("gmo".to_string(), vec!["merge".to_string(), "-Xtheirs".to_string()]);
    aliases.insert("mm".to_string(), vec!["merge".to_string(), "-Xours".to_string()]);
    aliases.insert("gmm".to_string(), vec!["merge".to_string(), "-Xours".to_string()]);

    // rebase
    aliases.insert("rb".to_string(), vec!["rebase".to_string()]);
    aliases.insert("grb".to_string(), vec!["rebase".to_string()]);
    aliases.insert("rbi".to_string(), vec!["rebase".to_string(), "-i".to_string()]);
    aliases.insert("grbi".to_string(), vec!["rebase".to_string(), "-i".to_string()]);
    aliases.insert("rbc".to_string(), vec!["rebase".to_string(), "--continue".to_string()]);
    aliases.insert("grbc".to_string(), vec!["rebase".to_string(), "--continue".to_string()]);
    aliases.insert("rbun".to_string(), vec!["rebase".to_string(), "--abort".to_string()]);
    aliases.insert("grbun".to_string(), vec!["rebase".to_string(), "--abort".to_string()]);
    aliases.insert("rbvi".to_string(), vec!["rebase".to_string(), "--edit-todo".to_string()]);
    aliases.insert("grbvi".to_string(), vec!["rebase".to_string(), "--edit-todo".to_string()]);
    aliases.insert("rbsk".to_string(), vec!["rebase".to_string(), "--skip".to_string()]);
    aliases.insert("grbsk".to_string(), vec!["rebase".to_string(), "--skip".to_string()]);

    // clone
    aliases.insert("clo".to_string(), vec!["clone".to_string()]);
    aliases.insert("gclo".to_string(), vec!["clone".to_string()]);
    aliases.insert("clob".to_string(), vec!["clone".to_string(), "-b".to_string()]);
    aliases.insert("gclob".to_string(), vec!["clone".to_string(), "-b".to_string()]);

    // tag
    aliases.insert("t".to_string(), vec!["tag".to_string()]);
    aliases.insert("gt".to_string(), vec!["tag".to_string()]);
    aliases.insert("tl".to_string(), vec!["tag".to_string(), "-l".to_string()]);
    aliases.insert("gtl".to_string(), vec!["tag".to_string(), "-l".to_string()]);
    aliases.insert("tn".to_string(), vec!["tag".to_string(), "-n".to_string()]);
    aliases.insert("gtn".to_string(), vec!["tag".to_string(), "-n".to_string()]);
    aliases.insert("ta".to_string(), vec!["tag".to_string(), "-a".to_string()]);
    aliases.insert("gta".to_string(), vec!["tag".to_string(), "-a".to_string()]);

    // blame
    aliases.insert("bl".to_string(), vec!["blame".to_string()]);
    aliases.insert("gbl".to_string(), vec!["blame".to_string()]);

    // worktree
    aliases.insert("w".to_string(), vec!["worktree".to_string()]);
    aliases.insert("gw".to_string(), vec!["worktree".to_string()]);
    aliases.insert("wa".to_string(), vec!["worktree".to_string(), "add".to_string()]);
    aliases.insert("gwa".to_string(), vec!["worktree".to_string(), "add".to_string()]);
    aliases.insert("wrm".to_string(), vec!["worktree".to_string(), "remove".to_string()]);
    aliases.insert("gwrm".to_string(), vec!["worktree".to_string(), "remove".to_string()]);
    aliases.insert("wl".to_string(), vec!["worktree".to_string(), "list".to_string()]);
    aliases.insert("gwl".to_string(), vec!["worktree".to_string(), "list".to_string()]);
    aliases.insert("wlck".to_string(), vec!["worktree".to_string(), "lock".to_string()]);
    aliases.insert("gwlck".to_string(), vec!["worktree".to_string(), "lock".to_string()]);
    aliases.insert("wun".to_string(), vec!["worktree".to_string(), "unlock".to_string()]);
    aliases.insert("gwun".to_string(), vec!["worktree".to_string(), "unlock".to_string()]);

    // clean
    aliases.insert(
        "cln".to_string(),
        vec!["clean".to_string(), "--interactive".to_string(), "-d".to_string()],
    );
    aliases.insert(
        "gcln".to_string(),
        vec!["clean".to_string(), "--interactive".to_string(), "-d".to_string()],
    );
    aliases.insert(
        "clnf".to_string(),
        vec!["clean".to_string(), "-d".to_string(), "--force".to_string()],
    );
    aliases.insert(
        "gclnf".to_string(),
        vec!["clean".to_string(), "-d".to_string(), "--force".to_string()],
    );
    aliases.insert(
        "clnfx".to_string(),
        vec!["clean".to_string(), "-d".to_string(), "--force".to_string(), "-x".to_string()],
    );
    aliases.insert(
        "gclnfx".to_string(),
        vec!["clean".to_string(), "-d".to_string(), "--force".to_string(), "-x".to_string()],
    );

    aliases
}

pub fn list_aliases(aliases: &HashMap<String, Vec<String>>, filter: Option<&str>) {
    let groups = get_alias_groups(aliases);

    println!("{}", "GIT-SHORT(1)".cyan().bold());
    println!();
    println!("{}", "NAME".yellow().bold());
    println!("       g - Git Alias Tool");
    println!();
    println!("{}", "ALIASES".yellow().bold());
    println!();

    let group_order = [
        "Add",
        "Status",
        "Commit",
        "Push",
        "Pull",
        "Branch",
        "Checkout",
        "Switch",
        "Log",
        "Diff",
        "Reset/Restore",
        "Revert",
        "Stash",
        "Remote",
        "Fetch",
        "Merge",
        "Rebase",
        "Clone",
        "Tag",
        "Blame",
        "Worktree",
        "Clean",
    ];

    let mut total_count = 0;

    for group_name in &group_order {
        if let Some(aliases_in_group) = groups.get(*group_name) {
            let filtered: Vec<_> = if let Some(f) = filter {
                aliases_in_group
                    .iter()
                    .filter(|(alias, cmd)| {
                        if alias.starts_with("g") {
                            return false;
                        }
                        cmd.first().map_or(false, |c| c.to_lowercase().contains(&f.to_lowercase()))
                    })
                    .collect()
            } else {
                aliases_in_group.iter().filter(|(alias, _)| !alias.starts_with("g")).collect()
            };

            if !filtered.is_empty() {
                println!("  {}:", group_name.green());
                for (alias, command) in filtered {
                    let cmd = command.join(" ");
                    println!("    {:<10} {}", alias.cyan(), format!("git {}", cmd).dimmed());
                    total_count += 1;
                }
                println!();
            }
        }
    }

    println!("{}", "─".repeat(50).cyan());
    if filter.is_some() {
        println!("  {} aliases matching '{}'", total_count, filter.unwrap().yellow());
    } else {
        println!("  {} aliases total", aliases.len());
    }
}

fn get_alias_groups(
    aliases: &HashMap<String, Vec<String>>,
) -> HashMap<String, Vec<(&String, &Vec<String>)>> {
    let mut groups: HashMap<String, Vec<(&String, &Vec<String>)>> = HashMap::new();

    let mut sorted: Vec<_> = aliases.iter().collect();
    sorted.sort_by_key(|(k, _)| k.to_string());

    for (alias, command) in sorted {
        let group = match alias.as_str() {
            "a" | "aa" => "Add",
            "s" | "ss" | "sb" => "Status",
            "cm" | "cma" | "cmn" | "cmm" | "cmai" | "gcm" | "gcma" | "gcmn" | "gcmm" | "gcmai" => {
                "Commit"
            }
            "ps" | "gps" | "psf" | "gpsf" | "psu" | "gpsu" => "Push",
            "p" | "gp" | "pl" | "pla" | "gpla" => "Pull",
            "b" | "ba" | "bra" | "bv" | "bc" | "gbc" | "bcr" | "gbcr" | "bd" | "gbd" => "Branch",
            "ck" | "ckb" => "Checkout",
            "sw" | "swc" | "swd" | "swf" => "Switch",
            "l" | "lg" | "lgg" | "ls" | "gls" | "glss" | "lss" | "lp" | "glp" => "Log",
            "d" | "di" | "dc" | "ds" | "dw" => "Diff",
            "rs" | "rsh" | "rss" | "uns" | "un" => "Reset/Restore",
            "rvr" => "Revert",
            "st" | "stp" | "sta" | "stl" | "std" => "Stash",
            "r" | "rv" | "ra" | "rd" => "Remote",
            "f" | "fa" => "Fetch",
            "m" | "gm" | "mf" | "gmf" | "mo" | "gmo" | "mm" | "gmm" => "Merge",
            "rb" | "rbi" | "rbc" | "grbc" | "rbun" | "grbun" | "rbvi" | "grbvi" | "rbsk"
            | "grbsk" => "Rebase",
            "clo" | "gclo" | "clob" | "gclob" => "Clone",
            "t" | "tl" => "Tag",
            "bl" => "Blame",
            "w" | "gw" | "wa" | "gwa" | "wl" | "gwl" | "wlck" | "gwlck" | "wrm" | "gwrm"
            | "wun" | "gwun" => "Worktree",
            "cln" | "gcln" | "clnf" | "gclnf" | "clnfx" | "gclnfx" => "Clean",
            _ => "Other",
        };

        groups.entry(group.to_string()).or_insert_with(Vec::new).push((alias, command));
    }

    groups
}