mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-03 12:36:57 -04:00
Compare commits
718
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
150260c8a1 | ||
|
|
49df908dd3 | ||
|
|
fdc54b7455 | ||
|
|
607034a61e | ||
|
|
ee173ff7c9 | ||
|
|
761c77f5a2 | ||
|
|
f9e8428061 | ||
|
|
9d840088ac | ||
|
|
b133318b40 | ||
|
|
24e79a057c | ||
|
|
c66667c8c1 | ||
|
|
e8e7ddea45 | ||
|
|
6322944a5e | ||
|
|
510f9a1ae1 | ||
|
|
9b2a5f636a | ||
|
|
e1aa68a7bd | ||
|
|
cf5d4d4f8e | ||
|
|
bd7fabef1f | ||
|
|
1a38d515d7 | ||
|
|
0f9d9e13d1 | ||
|
|
c07b3fad64 | ||
|
|
9bf3063457 | ||
|
|
7bddf53223 | ||
|
|
0aa6109d4d | ||
|
|
cb1b13e95e | ||
|
|
f9876c9742 | ||
|
|
d28a2ec059 | ||
|
|
f226a277bf | ||
|
|
cce29209be | ||
|
|
efb6524fa0 | ||
|
|
a65f003ccc | ||
|
|
b485363006 | ||
|
|
7fb5266027 | ||
|
|
ae89dde969 | ||
|
|
12500be554 | ||
|
|
05b97c8c8e | ||
|
|
0402674ee7 | ||
|
|
269ef7f250 | ||
|
|
798225d9e1 | ||
|
|
b7d4db2446 | ||
|
|
3d9f1e02e5 | ||
|
|
74d937881e | ||
|
|
e72c759541 | ||
|
|
9cd69e46df | ||
|
|
5511cc170e | ||
|
|
41d5f4dbb5 | ||
|
|
f0de880136 | ||
|
|
44e2542e4a | ||
|
|
a5f3515ad8 | ||
|
|
a67ad44781 | ||
|
|
36134006c5 | ||
|
|
3215839524 | ||
|
|
c2218133bc | ||
|
|
7c3d8921b7 | ||
|
|
221ebdc1fb | ||
|
|
2c9b4770bc | ||
|
|
9867180202 | ||
|
|
8dec35ba67 | ||
|
|
74e07080d0 | ||
|
|
ab3004bcd5 | ||
|
|
1ea0c270df | ||
|
|
51fb82d6bf | ||
|
|
280b4d60f8 | ||
|
|
54bd94ad24 | ||
|
|
8840c1a2b7 | ||
|
|
d08fafb1c4 | ||
|
|
f3eb180f75 | ||
|
|
c0c3aac02e | ||
|
|
24a4302c52 | ||
|
|
e887a2eb3c | ||
|
|
8a94663df1 | ||
|
|
8062f96d6b | ||
|
|
cf59b40a1b | ||
|
|
53acbc8f18 | ||
|
|
36e57d16bd | ||
|
|
080aa78266 | ||
|
|
fc8998e377 | ||
|
|
d4a0ca35c7 | ||
|
|
f79305090b | ||
|
|
f133224683 | ||
|
|
83337d9fa8 | ||
|
|
84e1d15079 | ||
|
|
09a24ee97d | ||
|
|
99a3ccde71 | ||
|
|
8ca8a43968 | ||
|
|
9fa43394fe | ||
|
|
37590a495c | ||
|
|
ee106f9af8 | ||
|
|
23a98937b4 | ||
|
|
a0b63090e0 | ||
|
|
53a8bd2e3f | ||
|
|
e9962b98a7 | ||
|
|
a1ce6029c1 | ||
|
|
8c716184c1 | ||
|
|
5c888a0b47 | ||
|
|
498092a8ec | ||
|
|
caf6a3629d | ||
|
|
1ca96bbe5b | ||
|
|
cb5d0bca1c | ||
|
|
ef3d6f4a32 | ||
|
|
b470442a46 | ||
|
|
bf01c0b00e | ||
|
|
76e39af76f | ||
|
|
5b91cd0cc8 | ||
|
|
6255728e63 | ||
|
|
b657fc4f0b | ||
|
|
d294d51791 | ||
|
|
b35f8776e1 | ||
|
|
8ca78412ac | ||
|
|
33f933ba21 | ||
|
|
d70dd5123d | ||
|
|
15da702140 | ||
|
|
cd50c79ae4 | ||
|
|
3ebba5f32c | ||
|
|
9a423c388d | ||
|
|
daf9b8cfa9 | ||
|
|
b6a9220343 | ||
|
|
aeb017e029 | ||
|
|
a6174271aa | ||
|
|
517e0f8248 | ||
|
|
c1cb95db6f | ||
|
|
966e5f5337 | ||
|
|
f244ec8251 | ||
|
|
2b97f0fb43 | ||
|
|
af5e25cfb5 | ||
|
|
93cae68e94 | ||
|
|
6e6fe6a489 | ||
|
|
2c2436574d | ||
|
|
0cdca9ac2c | ||
|
|
4172be6bc8 | ||
|
|
d97b37a178 | ||
|
|
21334fa889 | ||
|
|
36a29f225b | ||
|
|
1e85c4379f | ||
|
|
470632b97a | ||
|
|
50044dd5e0 | ||
|
|
bc330b8ff3 | ||
|
|
7f36494eb2 | ||
|
|
85c48ba887 | ||
|
|
1e3935cbaf | ||
|
|
3fe491fcb2 | ||
|
|
66b608b2f9 | ||
|
|
4ee01d153b | ||
|
|
79e04fad9a | ||
|
|
6778bc04a3 | ||
|
|
d548f857a4 | ||
|
|
f99c59b6d5 | ||
|
|
0fd4983c66 | ||
|
|
240948b882 | ||
|
|
cf82e69bbe | ||
|
|
653e59a3d5 | ||
|
|
e342860ef1 | ||
|
|
569adae6a2 | ||
|
|
79fe885dcd | ||
|
|
a46f26e148 | ||
|
|
ca4b8b25f0 | ||
|
|
dad2c5fa52 | ||
|
|
8a08abcd35 | ||
|
|
b96befa250 | ||
|
|
8cc820668a | ||
|
|
ccb1ee04a5 | ||
|
|
d00936fb4e | ||
|
|
e84d5acd23 | ||
|
|
a8a4211d2b | ||
|
|
6907816af9 | ||
|
|
38db574de9 | ||
|
|
c7012528fc | ||
|
|
2162e5ff64 | ||
|
|
f40f5710f0 | ||
|
|
97940cae10 | ||
|
|
1555503493 | ||
|
|
1a035db4c8 | ||
|
|
df5b3693d6 | ||
|
|
b123719107 | ||
|
|
6ec109c15a | ||
|
|
dee1ff007d | ||
|
|
02b739743a | ||
|
|
f5361fdcb4 | ||
|
|
b86d5bd688 | ||
|
|
4bfffa69ff | ||
|
|
f9b4bcde38 | ||
|
|
aaecd6cc40 | ||
|
|
7e5f25e415 | ||
|
|
d8059d7f7d | ||
|
|
0f2b79a1d4 | ||
|
|
bb87642aee | ||
|
|
4a5b3eaa52 | ||
|
|
1b4e76797f | ||
|
|
58971182ca | ||
|
|
9427a85805 | ||
|
|
d145e818d0 | ||
|
|
e0fc8fe25b | ||
|
|
bb705d91a4 | ||
|
|
738fa286b2 | ||
|
|
1d1b8cc01f | ||
|
|
c357284e1a | ||
|
|
232596b83d | ||
|
|
1c1d558cc7 | ||
|
|
dffb16ed96 | ||
|
|
df8ce76bd6 | ||
|
|
4d18b62c54 | ||
|
|
8193731a82 | ||
|
|
1a6d062192 | ||
|
|
1ff13cdfc6 | ||
|
|
19e8cafe41 | ||
|
|
cbb5fe6007 | ||
|
|
c4fc30c243 | ||
|
|
117aa1dcc6 | ||
|
|
c550737a4f | ||
|
|
9e37ae3f5d | ||
|
|
c89ef8b84a | ||
|
|
23befdd13a | ||
|
|
58a83b0862 | ||
|
|
d5b4f7bb3e | ||
|
|
3cee4de39c | ||
|
|
f609a04671 | ||
|
|
7ffb6ffb0f | ||
|
|
3691856021 | ||
|
|
b5ca6a3add | ||
|
|
ecaa4846f1 | ||
|
|
787f9966ec | ||
|
|
013cfc77a1 | ||
|
|
16f7b01fec | ||
|
|
421c6565f9 | ||
|
|
d02deeefd8 | ||
|
|
235f5bb221 | ||
|
|
be3b4bd791 | ||
|
|
67d6447e12 | ||
|
|
fd9d7cb7bb | ||
|
|
3d6965ccbb | ||
|
|
707fa37160 | ||
|
|
7075b66bc6 | ||
|
|
9d55d71fdd | ||
|
|
cc9a20c4ab | ||
|
|
c39fafe6ec | ||
|
|
2a11725749 | ||
|
|
deed9eb18e | ||
|
|
50b49ebeb1 | ||
|
|
a74c6eef40 | ||
|
|
a3759c65e4 | ||
|
|
519760077b | ||
|
|
8390622f70 | ||
|
|
a04fbafcfd | ||
|
|
4fe8dee40f | ||
|
|
6fd80565c7 | ||
|
|
5ebd8ac7fe | ||
|
|
3cda1d03d9 | ||
|
|
d4eb02fac0 | ||
|
|
9c72d8a2b0 | ||
|
|
4f3127ccb8 | ||
|
|
877c27722f | ||
|
|
0dda8b58d1 | ||
|
|
e997d1ae5d | ||
|
|
3e2ef84d56 | ||
|
|
b2eccd6fe8 | ||
|
|
cc25a3b8c5 | ||
|
|
e93d945dba | ||
|
|
246e08096f | ||
|
|
860a52a736 | ||
|
|
18d8b29461 | ||
|
|
7af371701d | ||
|
|
5ccc95b76f | ||
|
|
cdb1d76484 | ||
|
|
9e423e949c | ||
|
|
e1ceb6892a | ||
|
|
40b8557608 | ||
|
|
92e107f52d | ||
|
|
2f6a87df98 | ||
|
|
2c29577e3c | ||
|
|
e72559bb27 | ||
|
|
6da1cf87b1 | ||
|
|
508b869773 | ||
|
|
59cc6843e6 | ||
|
|
f108fd2236 | ||
|
|
8081b59a02 | ||
|
|
26d180a50a | ||
|
|
10fe872c71 | ||
|
|
c74448f00d | ||
|
|
41ab7c44a0 | ||
|
|
3589a43682 | ||
|
|
ad70341139 | ||
|
|
ea93df571d | ||
|
|
bc21921001 | ||
|
|
07cbb62510 | ||
|
|
fc868cdda5 | ||
|
|
864a9ada57 | ||
|
|
f3e9d50d94 | ||
|
|
cdad0b998e | ||
|
|
64012d67a9 | ||
|
|
33d9d4dbf1 | ||
|
|
4c5e250ed8 | ||
|
|
1359fa14c1 | ||
|
|
c222a618a8 | ||
|
|
05c32e292e | ||
|
|
fb4f742416 | ||
|
|
276438b601 | ||
|
|
edec116ceb | ||
|
|
1aae1772ce | ||
|
|
a642395e9f | ||
|
|
70bfeddc90 | ||
|
|
e2a966443b | ||
|
|
0b13c3ca87 | ||
|
|
8b6766de79 | ||
|
|
c9371f812f | ||
|
|
e592d81b60 | ||
|
|
f2f50ccf75 | ||
|
|
75aed98c35 | ||
|
|
7f9818cfa2 | ||
|
|
679148449a | ||
|
|
bc00aeb10d | ||
|
|
4d258bd981 | ||
|
|
c465b0f2ff | ||
|
|
25160b671e | ||
|
|
20bfa42792 | ||
|
|
5a740e34c7 | ||
|
|
0aad599a9b | ||
|
|
b6c892a08a | ||
|
|
28d12e4e5d | ||
|
|
5d5e24a48e | ||
|
|
de598e55a6 | ||
|
|
0fd8392067 | ||
|
|
67ac2c5d9b | ||
|
|
7626fd7df3 | ||
|
|
db409fa69f | ||
|
|
5b8a8d356c | ||
|
|
d7e2ca3f10 | ||
|
|
387fbf6ab6 | ||
|
|
917eb88617 | ||
|
|
005827395d | ||
|
|
7f9fa64074 | ||
|
|
ab06a1c85c | ||
|
|
37048911ca | ||
|
|
2b7b6f71ee | ||
|
|
47d422bb8a | ||
|
|
c3ca77d6bf | ||
|
|
a3cd1e93be | ||
|
|
4cf8d81155 | ||
|
|
7774fe0ab3 | ||
|
|
f7db17f7d0 | ||
|
|
1106981827 | ||
|
|
1dac4158e9 | ||
|
|
18c5780485 | ||
|
|
e895052437 | ||
|
|
ade8d78c63 | ||
|
|
2e74b7177e | ||
|
|
6266e19623 | ||
|
|
c67aa49856 | ||
|
|
3a54089859 | ||
|
|
e2c447b8d0 | ||
|
|
843e12286f | ||
|
|
e60936e964 | ||
|
|
b9cfd89b80 | ||
|
|
de4224bbe4 | ||
|
|
ce91de76e4 | ||
|
|
acfce07aa0 | ||
|
|
81216189e4 | ||
|
|
2b26b380b6 | ||
|
|
1ba8d3060b | ||
|
|
f561007fb7 | ||
|
|
a63d5891e2 | ||
|
|
df38e954f4 | ||
|
|
ea532b4729 | ||
|
|
572d1b5920 | ||
|
|
e8fac6ca73 | ||
|
|
4de3fadb00 | ||
|
|
12f24aa8b4 | ||
|
|
911aa7774b | ||
|
|
1fb0e1e151 | ||
|
|
94bf279b5a | ||
|
|
37381b610d | ||
|
|
6d4df57393 | ||
|
|
3df01aaff0 | ||
|
|
4ee4f6f34b | ||
|
|
7953f7fa86 | ||
|
|
7a8df7795c | ||
|
|
aa493d3a9e | ||
|
|
72731f2c16 | ||
|
|
f680b6e82e | ||
|
|
ec22570eac | ||
|
|
198ead7c14 | ||
|
|
297a020abf | ||
|
|
473d989cde | ||
|
|
061bfce835 | ||
|
|
996e30e5d9 | ||
|
|
ecd2a14a15 | ||
|
|
8dfa8dc48c | ||
|
|
f7c183a429 | ||
|
|
473f86fcaa | ||
|
|
28353da61b | ||
|
|
efd49f07fd | ||
|
|
b8e183acc4 | ||
|
|
821c4b05fe | ||
|
|
4272d84fa2 | ||
|
|
e95505453e | ||
|
|
6dc34d19ea | ||
|
|
a670fbb33c | ||
|
|
98e6c119f5 | ||
|
|
c718a73d0a | ||
|
|
d74c817fd8 | ||
|
|
93d19db158 | ||
|
|
d7b611aa05 | ||
|
|
fc6008fdff | ||
|
|
a65d3119c0 | ||
|
|
51ecf4089b | ||
|
|
0c0fe8997b | ||
|
|
f86309dd03 | ||
|
|
c31fcb7134 | ||
|
|
91ec42f3f8 | ||
|
|
8f628296ad | ||
|
|
61bd3e8dd2 | ||
|
|
7263630967 | ||
|
|
16711c6f1a | ||
|
|
b2023f10b6 | ||
|
|
e915488a83 | ||
|
|
b2d629b50a | ||
|
|
125d4fa9dc | ||
|
|
527a1596f3 | ||
|
|
51d9f70f9e | ||
|
|
83727d48b5 | ||
|
|
8efc175340 | ||
|
|
6a6cb25d7e | ||
|
|
fd782ff568 | ||
|
|
dbfb469bad | ||
|
|
888a976fc0 | ||
|
|
2073730186 | ||
|
|
7a4a0c85c4 | ||
|
|
382ecb6bfe | ||
|
|
03694f7502 | ||
|
|
ee308a4994 | ||
|
|
a2b2336173 | ||
|
|
d7b1deb465 | ||
|
|
dd01639f57 | ||
|
|
525932fbf2 | ||
|
|
b1314349d7 | ||
|
|
9671f549a1 | ||
|
|
a1738a77ae | ||
|
|
689deb72bd | ||
|
|
84372cfad9 | ||
|
|
e429415ed4 | ||
|
|
7402be98b6 | ||
|
|
341b9725d4 | ||
|
|
8f164f7bc5 | ||
|
|
79c11a0458 | ||
|
|
4a4afc4639 | ||
|
|
ebdfd8046a | ||
|
|
d99e983236 | ||
|
|
1c6cfafba7 | ||
|
|
83d642b74f | ||
|
|
b1bc437d1b | ||
|
|
26989ce0ee | ||
|
|
e6356ce10c | ||
|
|
b92da0dc54 | ||
|
|
70e668bfcf | ||
|
|
8dd517870d | ||
|
|
f1753f36c8 | ||
|
|
3ea81d4a6f | ||
|
|
0df5cb1286 | ||
|
|
c43830b027 | ||
|
|
08624b8ef7 | ||
|
|
73b68927af | ||
|
|
bf699d3a79 | ||
|
|
f2e8d549ba | ||
|
|
4ffb6c0fea | ||
|
|
54776052a1 | ||
|
|
9c5eedf748 | ||
|
|
ca08956f77 | ||
|
|
aa74239f05 | ||
|
|
9e7018db8a | ||
|
|
cdea5b4873 | ||
|
|
4b0432423d | ||
|
|
2607580a09 | ||
|
|
ebd56bd8d5 | ||
|
|
ed1547e0cb | ||
|
|
5e388e21c8 | ||
|
|
4c89f9fba5 | ||
|
|
8e7958f78b | ||
|
|
579791e7bc | ||
|
|
595e28d335 | ||
|
|
0551f29de9 | ||
|
|
82b5c20050 | ||
|
|
ecaf1e9002 | ||
|
|
69ff621494 | ||
|
|
f32fe84c9b | ||
|
|
2ded352f3a | ||
|
|
c877a8528f | ||
|
|
d1754a9490 | ||
|
|
33a96a3dd7 | ||
|
|
cd889adfa0 | ||
|
|
77447ea6c3 | ||
|
|
fb05ee369f | ||
|
|
213da4fddd | ||
|
|
e78a09ebab | ||
|
|
7ccb871a45 | ||
|
|
9cc18bd7e6 | ||
|
|
8e2ecd17a9 | ||
|
|
78676dcff6 | ||
|
|
7847203d6e | ||
|
|
af3101c7f2 | ||
|
|
ec7e9f9228 | ||
|
|
ab5875c78f | ||
|
|
f6af4c29d4 | ||
|
|
996ad5bf26 | ||
|
|
096628e366 | ||
|
|
b432fb5efe | ||
|
|
c390c9d58e | ||
|
|
e25403c650 | ||
|
|
5c9a9e777c | ||
|
|
39d24fdeb7 | ||
|
|
bbb2b32816 | ||
|
|
0152639ef0 | ||
|
|
c43195efb6 | ||
|
|
17db918cba | ||
|
|
befd7fe63e | ||
|
|
de28391052 | ||
|
|
92f0aa23cc | ||
|
|
c8520fbe78 | ||
|
|
8ce60662f2 | ||
|
|
c5acbb6c7c | ||
|
|
4aca854b59 | ||
|
|
f7bf125037 | ||
|
|
c92ed07082 | ||
|
|
df0c3b3ea8 | ||
|
|
280b0429c3 | ||
|
|
cb22db675a | ||
|
|
bb21034972 | ||
|
|
ec5bc93576 | ||
|
|
f43fd7af79 | ||
|
|
a200fccba9 | ||
|
|
37dc31b815 | ||
|
|
1712ad08ae | ||
|
|
53f0c1eb4f | ||
|
|
c53adbbb84 | ||
|
|
e932aaaeaf | ||
|
|
b44d0c4bde | ||
|
|
917cfd7586 | ||
|
|
c7e6a73512 | ||
|
|
b7ba06fa5b | ||
|
|
51e205ce11 | ||
|
|
6984a4f4d4 | ||
|
|
4baecec7bf | ||
|
|
b262e7f9b8 | ||
|
|
b92c294059 | ||
|
|
07d03df8df | ||
|
|
9cc1d65280 | ||
|
|
893c1cab75 | ||
|
|
25d57350df | ||
|
|
eb68591396 | ||
|
|
6de9e230a0 | ||
|
|
668d29736c | ||
|
|
be667682f0 | ||
|
|
045bce5dfc | ||
|
|
3827479643 | ||
|
|
d41a195ee6 | ||
|
|
71d2fd37e2 | ||
|
|
66de981e91 | ||
|
|
375451785c | ||
|
|
a6af31a4cb | ||
|
|
94daf7bddc | ||
|
|
4eb73393bb | ||
|
|
f5c9764dd2 | ||
|
|
6dc25d796b | ||
|
|
0c07963a2e | ||
|
|
092d5dd608 | ||
|
|
e9bbd816de | ||
|
|
eb6f089a2a | ||
|
|
cb240081a8 | ||
|
|
9c57444adc | ||
|
|
7b8ebfa27e | ||
|
|
8ab05d6834 | ||
|
|
774df817fd | ||
|
|
18903a7dde | ||
|
|
7cfbfb7183 | ||
|
|
975d2bedb6 | ||
|
|
5c78394299 | ||
|
|
e33fe37a99 | ||
|
|
ea54cb6e9c | ||
|
|
08f0e28e55 | ||
|
|
2d4706e96e | ||
|
|
d30eef69b1 | ||
|
|
91909331b5 | ||
|
|
f31e213edc | ||
|
|
7b302d8c29 | ||
|
|
a1fae41051 | ||
|
|
b16bb409fc | ||
|
|
a77d24fdc6 | ||
|
|
eecf07cd12 | ||
|
|
06be88aef7 | ||
|
|
4c5b1574f1 | ||
|
|
de57cfd6ff | ||
|
|
2b24c15938 | ||
|
|
e874f94cf8 | ||
|
|
0a410141ae | ||
|
|
e356b29b4a | ||
|
|
bc4ce26cef | ||
|
|
ae66f720f5 | ||
|
|
9c15ba0c0b | ||
|
|
b3060065d9 | ||
|
|
a313b16704 | ||
|
|
b93b9dae88 | ||
|
|
277142fc4b | ||
|
|
18a508b29c | ||
|
|
cdfad864ae | ||
|
|
fb4453c18a | ||
|
|
b5ff55e538 | ||
|
|
81a9133261 | ||
|
|
ca6f9c4155 | ||
|
|
7569180cac | ||
|
|
eeec373728 | ||
|
|
0604e43813 | ||
|
|
27ade502ee | ||
|
|
3a7468ecac | ||
|
|
7b05dacb98 | ||
|
|
b73efb2c22 | ||
|
|
a06a5cadee | ||
|
|
3cd2d6fa5c | ||
|
|
ec839e9e96 | ||
|
|
6f2f9f6677 | ||
|
|
2082fdf84a | ||
|
|
894485190b | ||
|
|
87b2455dbb | ||
|
|
2e68967e02 | ||
|
|
71422a8549 | ||
|
|
9c69a5df69 | ||
|
|
9b24995990 | ||
|
|
142f06357f | ||
|
|
18ea68c23a | ||
|
|
4b2622d93b | ||
|
|
ae0193698e | ||
|
|
6b4a638415 | ||
|
|
4b3c9f5b35 | ||
|
|
6c69549ced | ||
|
|
5868750aba | ||
|
|
ab3052f642 | ||
|
|
53f4ccb809 | ||
|
|
077ae99438 | ||
|
|
fe8adf9eb8 | ||
|
|
c713d550c0 | ||
|
|
d19d89ea9d | ||
|
|
e8ec41fb0f | ||
|
|
7682ec029b | ||
|
|
03f726038e | ||
|
|
796945aad0 | ||
|
|
db02c13bf6 | ||
|
|
1ce9a87544 | ||
|
|
35e6e6347a | ||
|
|
54708233ac | ||
|
|
c679fd1924 | ||
|
|
9a79154d05 | ||
|
|
60872c91e6 | ||
|
|
afc4aedd4f | ||
|
|
f8ba899b87 | ||
|
|
52447e5d46 | ||
|
|
6794149ec8 | ||
|
|
a4772ae606 | ||
|
|
f30e09856c | ||
|
|
9b7f978e3e | ||
|
|
f17417219a | ||
|
|
d7f84aed8a | ||
|
|
deecbadda9 | ||
|
|
1431ffcebf | ||
|
|
1db1fee03a | ||
|
|
2f0116170d | ||
|
|
429225da80 | ||
|
|
39b77c0fca | ||
|
|
63e5790410 | ||
|
|
272e021c08 | ||
|
|
862ebd25cb | ||
|
|
5d8a85f7e7 | ||
|
|
5f30ccfbc3 | ||
|
|
71cab4fadc | ||
|
|
09ce430240 | ||
|
|
6be9109aaa | ||
|
|
67a7293e79 | ||
|
|
decb055df9 | ||
|
|
75674d819c | ||
|
|
35c430c8c9 | ||
|
|
94426de533 | ||
|
|
c4e27bf96c | ||
|
|
57bb1aa698 | ||
|
|
02270e9ccd | ||
|
|
1199c18b53 | ||
|
|
4f807eeb19 | ||
|
|
7c44b76477 | ||
|
|
c21633b1be | ||
|
|
1b05ba252c | ||
|
|
28474b08ee | ||
|
|
6f13b42279 | ||
|
|
8637587b82 | ||
|
|
f581dc4a56 | ||
|
|
693e9fc152 | ||
|
|
c595833883 | ||
|
|
7807b40322 | ||
|
|
b284970bac | ||
|
|
b46623ebef | ||
|
|
084c0a19bc | ||
|
|
3cee37388c | ||
|
|
a7969aef2c | ||
|
|
39c900c7e7 | ||
|
|
6e247c1583 | ||
|
|
87bf1dbc7f | ||
|
|
1f920ae6ba | ||
|
|
932e01b41a | ||
|
|
373f24c80f | ||
|
|
a548b289ef | ||
|
|
b168fc8cdd | ||
|
|
94845dcf98 | ||
|
|
1af6dff64e | ||
|
|
72de4f436e | ||
|
|
effda8291b | ||
|
|
7985e31020 | ||
|
|
866e0a618b | ||
|
|
a5ee61c117 | ||
|
|
08aad924d7 | ||
|
|
be02786dad | ||
|
|
949022db8c | ||
|
|
b1a090d4c0 | ||
|
|
39f3f150ed | ||
|
|
1a2a301aa2 |
@@ -0,0 +1,4 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.go]
|
||||||
|
indent_style = tab
|
||||||
@@ -2,9 +2,14 @@
|
|||||||
|
|
||||||
- **Please check if the PR fulfills these requirements**
|
- **Please check if the PR fulfills these requirements**
|
||||||
|
|
||||||
* [ ] Cheatsheets are up-to-date (run `go run scripts/cheatsheet/main.go generate`)
|
* [ ] Cheatsheets are up-to-date (run `go generate ./...`)
|
||||||
* [ ] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
|
* [ ] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting))
|
||||||
* [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide)
|
* [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide)
|
||||||
* [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
|
* [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation))
|
||||||
* [ ] Docs (specifically `docs/Config.md`) have been updated if necessary
|
* [ ] Docs (specifically `docs/Config.md`) have been updated if necessary
|
||||||
* [ ] You've read through your own file changes for silly mistakes etc
|
* [ ] You've read through your own file changes for silly mistakes etc
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Be sure to name your PR with an imperative e.g. 'Add worktrees view'
|
||||||
|
see https://github.com/jesseduffield/lazygit/releases/tag/v0.40.0 for examples
|
||||||
|
-->
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
changelog:
|
||||||
|
exclude:
|
||||||
|
labels:
|
||||||
|
- ignore-for-release
|
||||||
|
categories:
|
||||||
|
- title: Features ✨
|
||||||
|
labels:
|
||||||
|
- feature
|
||||||
|
- title: Enhancements 🔥
|
||||||
|
labels:
|
||||||
|
- enhancement
|
||||||
|
- title: Fixes 🔧
|
||||||
|
labels:
|
||||||
|
- bug
|
||||||
|
- title: Maintenance ⚙️
|
||||||
|
labels:
|
||||||
|
- maintenance
|
||||||
|
- title: Docs 📖
|
||||||
|
labels:
|
||||||
|
- docs
|
||||||
|
- title: I18n 🌎
|
||||||
|
labels:
|
||||||
|
- i18n
|
||||||
|
- title: Other Changes
|
||||||
|
labels:
|
||||||
|
- "*"
|
||||||
@@ -14,11 +14,15 @@ jobs:
|
|||||||
- name: Unshallow repo
|
- name: Unshallow repo
|
||||||
run: git fetch --prune --unshallow
|
run: git fetch --prune --unshallow
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.20.x
|
||||||
- name: Run goreleaser
|
- name: Run goreleaser
|
||||||
uses: goreleaser/goreleaser-action@v1
|
uses: goreleaser/goreleaser-action@v4
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: v1.17.2
|
||||||
|
args: release --clean
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_API_TOKEN}}
|
GITHUB_TOKEN: ${{secrets.GITHUB_API_TOKEN}}
|
||||||
homebrew:
|
homebrew:
|
||||||
|
|||||||
+73
-64
@@ -1,7 +1,7 @@
|
|||||||
name: Continuous Integration
|
name: Continuous Integration
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GO_VERSION: 1.18
|
GO_VERSION: 1.20
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -30,22 +30,20 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.20.x
|
||||||
- name: Cache build
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{matrix.cache_path}}
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
|
||||||
restore-keys: |
|
|
||||||
${{runner.os}}-go-
|
|
||||||
- name: Test code
|
- name: Test code
|
||||||
# we're passing -short so that we skip the integration tests, which will be run in parallel below
|
# we're passing -short so that we skip the integration tests, which will be run in parallel below
|
||||||
run: |
|
run: |
|
||||||
go test ./... -short
|
mkdir -p /tmp/code_coverage
|
||||||
|
go test ./... -short -cover -args "-test.gocoverdir=/tmp/code_coverage"
|
||||||
|
- name: Upload code coverage artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: coverage-unit-${{ matrix.os }}-${{ github.run_id }}
|
||||||
|
path: /tmp/code_coverage
|
||||||
|
|
||||||
integration-tests:
|
integration-tests:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -89,23 +87,23 @@ jobs:
|
|||||||
path: ~/git-${{matrix.git-version}}
|
path: ~/git-${{matrix.git-version}}
|
||||||
key: ${{runner.os}}-git-${{matrix.git-version}}
|
key: ${{runner.os}}-git-${{matrix.git-version}}
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.20.x
|
||||||
- name: Cache build
|
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
|
||||||
restore-keys: |
|
|
||||||
${{runner.os}}-go-
|
|
||||||
- name: Print git version
|
- name: Print git version
|
||||||
run: git --version
|
run: git --version
|
||||||
- name: Test code
|
- name: Test code
|
||||||
|
env:
|
||||||
|
# See https://go.dev/blog/integration-test-coverage
|
||||||
|
LAZYGIT_GOCOVERDIR: /tmp/code_coverage
|
||||||
run: |
|
run: |
|
||||||
|
mkdir -p /tmp/code_coverage
|
||||||
./scripts/run_integration_tests.sh
|
./scripts/run_integration_tests.sh
|
||||||
|
- name: Upload code coverage artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: coverage-integration-${{ matrix.git-version }}-${{ github.run_id }}
|
||||||
|
path: /tmp/code_coverage
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
@@ -115,18 +113,9 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.20.x
|
||||||
- name: Cache build
|
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-build
|
|
||||||
restore-keys: |
|
|
||||||
${{runner.os}}-go-
|
|
||||||
- name: Build linux binary
|
- name: Build linux binary
|
||||||
run: |
|
run: |
|
||||||
GOOS=linux go build
|
GOOS=linux go build
|
||||||
@@ -151,29 +140,21 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.20.x
|
||||||
- name: Cache build
|
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-build
|
|
||||||
restore-keys: |
|
|
||||||
${{runner.os}}-go-
|
|
||||||
- name: Check Cheatsheet
|
|
||||||
run: |
|
|
||||||
go run scripts/cheatsheet/main.go check
|
|
||||||
- name: Check Vendor Directory
|
- name: Check Vendor Directory
|
||||||
# ensure our vendor directory matches up with our go modules
|
# ensure our vendor directory matches up with our go modules
|
||||||
run: |
|
run: |
|
||||||
go mod vendor && git diff --exit-code || (echo "Unexpected change to vendor directory. Run 'go mod vendor' locally and commit the changes" && exit 1)
|
go mod vendor && git diff --exit-code || (echo "Unexpected change to vendor directory. Run 'go mod vendor' locally and commit the changes" && exit 1)
|
||||||
- name: Check Integration Test List
|
- name: Check go.mod file
|
||||||
# ensure our integration test list is up to date
|
# ensure our go.mod file is clean
|
||||||
run: |
|
run: |
|
||||||
go generate pkg/integration/tests/tests.go && git diff --exit-code || (echo "Integration test list not up to date. Run 'go generate pkg/integration/tests/tests.go' locally and commit the changes" && exit 1)
|
go mod tidy && git diff --exit-code || (echo "go.mod file is not clean. Run 'go mod tidy' locally and commit the changes" && exit 1)
|
||||||
|
- name: Check All Auto-Generated Files
|
||||||
|
# ensure all our auto-generated files are up to date
|
||||||
|
run: |
|
||||||
|
go generate ./... && git diff --quiet || (git status -s; echo "Auto-generated files not up to date. Run 'go generate ./...' locally and commit the changes" && exit 1)
|
||||||
shell: bash # needed so that we get "-o pipefail"
|
shell: bash # needed so that we get "-o pipefail"
|
||||||
- name: Check Filenames
|
- name: Check Filenames
|
||||||
run: scripts/check_filenames.sh
|
run: scripts/check_filenames.sh
|
||||||
@@ -185,22 +166,50 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.18.x
|
go-version: 1.20.x
|
||||||
- name: Cache build
|
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
|
||||||
restore-keys: |
|
|
||||||
${{runner.os}}-go-
|
|
||||||
- name: Lint
|
- name: Lint
|
||||||
uses: golangci/golangci-lint-action@v3.1.0
|
uses: golangci/golangci-lint-action@v3.7.0
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
- name: errors
|
- name: errors
|
||||||
run: golangci-lint run
|
run: golangci-lint run
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
check-required-label:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref != 'refs/heads/master'
|
||||||
|
steps:
|
||||||
|
- uses: mheap/github-action-required-labels@v5
|
||||||
|
with:
|
||||||
|
mode: exactly
|
||||||
|
count: 1
|
||||||
|
labels: "ignore-for-release, feature, enhancement, bug, maintenance, docs, i18n"
|
||||||
|
upload-coverage:
|
||||||
|
# List all jobs that produce coverage files
|
||||||
|
needs: [unit-tests, integration-tests]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Download all coverage artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
path: /tmp/code_coverage
|
||||||
|
|
||||||
|
- name: Combine coverage files
|
||||||
|
run: |
|
||||||
|
# Find all directories in /tmp/code_coverage and create a comma-separated list
|
||||||
|
COVERAGE_DIRS=$(find /tmp/code_coverage -mindepth 1 -maxdepth 1 -type d -printf '/tmp/code_coverage/%f,' | sed 's/,$//')
|
||||||
|
echo "Coverage directories: $COVERAGE_DIRS"
|
||||||
|
# Run the combine command with the generated list
|
||||||
|
go tool covdata textfmt -i=$COVERAGE_DIRS -o coverage.out
|
||||||
|
echo "Combined coverage:"
|
||||||
|
go tool cover -func coverage.out | tail -1 | awk '{print $3}'
|
||||||
|
|
||||||
|
- name: Upload to Codacy
|
||||||
|
run: |
|
||||||
|
CODACY_PROJECT_TOKEN=${{ secrets.CODACY_PROJECT_TOKEN }} \
|
||||||
|
bash <(curl -Ls https://coverage.codacy.com/get.sh) report \
|
||||||
|
--force-coverage-parser go -r coverage.out
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Generate Sponsors 💖
|
- name: Generate Sponsors 💖
|
||||||
uses: JamesIves/github-sponsors-readme-action@v1.0.8
|
uses: JamesIves/github-sponsors-readme-action@v1.2.2
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.SPONSORS_TOKEN }}
|
token: ${{ secrets.SPONSORS_TOKEN }}
|
||||||
file: 'README.md'
|
file: 'README.md'
|
||||||
|
|||||||
+6
-1
@@ -35,7 +35,12 @@ lazygit.exe
|
|||||||
|
|
||||||
test/git_server/data
|
test/git_server/data
|
||||||
|
|
||||||
test/results/**
|
test/_results/**
|
||||||
|
|
||||||
oryxBuildBinary
|
oryxBuildBinary
|
||||||
__debug_bin
|
__debug_bin
|
||||||
|
|
||||||
|
.worktrees
|
||||||
|
demo/output/*
|
||||||
|
|
||||||
|
coverage.out
|
||||||
|
|||||||
+7
-2
@@ -20,10 +20,15 @@ linters:
|
|||||||
linters-settings:
|
linters-settings:
|
||||||
exhaustive:
|
exhaustive:
|
||||||
default-signifies-exhaustive: true
|
default-signifies-exhaustive: true
|
||||||
|
staticcheck:
|
||||||
|
# SA1019 is for checking that we're not using fields marked as deprecated
|
||||||
|
# in a comment. It decides this in a loose way so I'm silencing it. Also because
|
||||||
|
# it's tripping on our own structs.
|
||||||
|
checks: ["all", "-SA1019"]
|
||||||
nakedret:
|
nakedret:
|
||||||
# the gods will judge me but I just don't like naked returns at all
|
# the gods will judge me but I just don't like naked returns at all
|
||||||
max-func-lines: 0
|
max-func-lines: 0
|
||||||
|
|
||||||
run:
|
run:
|
||||||
go: 1.18
|
go: '1.20'
|
||||||
|
timeout: 10m
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ builds:
|
|||||||
- amd64
|
- amd64
|
||||||
- arm
|
- arm
|
||||||
- arm64
|
- arm64
|
||||||
- 386
|
- '386'
|
||||||
# Default is `-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}`.
|
# Default is `-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}`.
|
||||||
ldflags:
|
ldflags:
|
||||||
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.buildSource=binaryRelease
|
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.buildSource=binaryRelease
|
||||||
|
|||||||
Vendored
+35
-10
@@ -7,11 +7,12 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "main.go",
|
"program": "main.go",
|
||||||
"args": ["--debug", "--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"],
|
"args": [
|
||||||
|
"--debug",
|
||||||
|
"--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"
|
||||||
|
],
|
||||||
|
"hideSystemGoroutines": true,
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"presentation": {
|
|
||||||
"hidden": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Tail Lazygit logs",
|
"name": "Tail Lazygit logs",
|
||||||
@@ -19,17 +20,41 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "main.go",
|
"program": "main.go",
|
||||||
"args": ["--logs", "--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"],
|
"args": [
|
||||||
|
"--logs",
|
||||||
|
"--use-config-file=${workspaceFolder}/.vscode/debugger_config.yml"
|
||||||
|
],
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"presentation": {
|
},
|
||||||
"hidden": true
|
{
|
||||||
}
|
"name": "Attach to a running Lazygit",
|
||||||
}
|
"type": "go",
|
||||||
|
"request": "attach",
|
||||||
|
"mode": "local",
|
||||||
|
"processId": "lazygit",
|
||||||
|
"hideSystemGoroutines": true,
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// To use this, first start an integration test with the "cli" runner and
|
||||||
|
// use the -debug option; e.g.
|
||||||
|
// $ make integration-test-cli -- -debug tag/reset.go
|
||||||
|
"name": "Attach to integration test runner",
|
||||||
|
"type": "go",
|
||||||
|
"request": "attach",
|
||||||
|
"mode": "local",
|
||||||
|
"processId": "test_lazygit",
|
||||||
|
"hideSystemGoroutines": true,
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"compounds": [
|
"compounds": [
|
||||||
{
|
{
|
||||||
"name": "Run with logs",
|
"name": "Run with logs",
|
||||||
"configurations": ["Tail Lazygit logs", "Debug Lazygit"],
|
"configurations": [
|
||||||
|
"Tail Lazygit logs",
|
||||||
|
"Debug Lazygit"
|
||||||
|
],
|
||||||
"stopAll": true
|
"stopAll": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"gopls": {
|
||||||
|
"formatting.gofumpt": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -10,6 +10,15 @@ before making a change.
|
|||||||
|
|
||||||
[This video](https://www.youtube.com/watch?v=kNavnhzZHtk) walks through the process of adding a small feature to lazygit. If you have no idea where to start, watching that video is a good first step.
|
[This video](https://www.youtube.com/watch?v=kNavnhzZHtk) walks through the process of adding a small feature to lazygit. If you have no idea where to start, watching that video is a good first step.
|
||||||
|
|
||||||
|
## Codebase guide
|
||||||
|
|
||||||
|
[This doc](./docs/dev/Codebase_Guide.md) explains:
|
||||||
|
* what the different packages in the codebase are for
|
||||||
|
* where important files live
|
||||||
|
* important concepts in the code
|
||||||
|
* how the event loop works
|
||||||
|
* other useful information
|
||||||
|
|
||||||
## All code changes happen through Pull Requests
|
## All code changes happen through Pull Requests
|
||||||
|
|
||||||
Pull requests are the best way to propose changes to the codebase. We actively
|
Pull requests are the best way to propose changes to the codebase. We actively
|
||||||
@@ -21,6 +30,8 @@ welcome your pull requests:
|
|||||||
4. Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
4. Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||||
5. Issue that pull request!
|
5. Issue that pull request!
|
||||||
|
|
||||||
|
Please do not raise pull request from your fork's master branch: make a feature branch instead. Lazygit maintainers will sometimes push changes to your branch when reviewing a PR and we often can't do this if you use your master branch.
|
||||||
|
|
||||||
If you've never written Go in your life, then join the club! Lazygit was the maintainer's first Go program, and most contributors have never used Go before. Go is widely considered an easy-to-learn language, so if you're looking for an open source project to gain dev experience, you've come to the right place.
|
If you've never written Go in your life, then join the club! Lazygit was the maintainer's first Go program, and most contributors have never used Go before. Go is widely considered an easy-to-learn language, so if you're looking for an open source project to gain dev experience, you've come to the right place.
|
||||||
|
|
||||||
## Running in a VSCode dev container
|
## Running in a VSCode dev container
|
||||||
@@ -97,6 +108,10 @@ To run gofumpt from your terminal go:
|
|||||||
go install mvdan.cc/gofumpt@latest && gofumpt -l -w .
|
go install mvdan.cc/gofumpt@latest && gofumpt -l -w .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Programming Font
|
||||||
|
|
||||||
|
Lazygit supports [Nerd Fonts](https://www.nerdfonts.com) to render certain icons. Sometimes we use some of these icons verbatim in string literals in the code (mainly in tests), so you need to set your development environment to use a nerd font to see these.
|
||||||
|
|
||||||
## Internationalisation
|
## Internationalisation
|
||||||
|
|
||||||
Boy that's a hard word to spell. Anyway, lazygit is translated into several languages within the pkg/i18n package. If you need to render text to the user, you should add a new field to the TranslationSet struct in `pkg/i18n/english.go` and add the actual content within the `EnglishTranslationSet()` method in the same file. Then you can access via `gui.Tr.YourNewText` (or `self.c.Tr.YourNewText`, etc). Although it is appreciated if you translate the text into other languages, it's not expected of you (google translate will likely do a bad job anyway!).
|
Boy that's a hard word to spell. Anyway, lazygit is translated into several languages within the pkg/i18n package. If you need to render text to the user, you should add a new field to the TranslationSet struct in `pkg/i18n/english.go` and add the actual content within the `EnglishTranslationSet()` method in the same file. Then you can access via `gui.Tr.YourNewText` (or `self.c.Tr.YourNewText`, etc). Although it is appreciated if you translate the text into other languages, it's not expected of you (google translate will likely do a bad job anyway!).
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
# docker build -t lazygit .
|
# docker build -t lazygit .
|
||||||
# docker run -it lazygit:latest /bin/sh
|
# docker run -it lazygit:latest /bin/sh
|
||||||
|
|
||||||
FROM golang:1.18 as build
|
FROM golang:1.20 as build
|
||||||
WORKDIR /go/src/github.com/jesseduffield/lazygit/
|
WORKDIR /go/src/github.com/jesseduffield/lazygit/
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
.PHONY: all
|
||||||
|
all: build
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
go build -gcflags='all=-N -l'
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install:
|
||||||
|
go install
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run: build
|
||||||
|
./lazygit
|
||||||
|
|
||||||
|
# Run `make run-debug` in one terminal tab and `make print-log` in another to view the program and its log output side by side
|
||||||
|
.PHONY: run-debug
|
||||||
|
run-debug:
|
||||||
|
go run main.go -debug
|
||||||
|
|
||||||
|
.PHONY: print-log
|
||||||
|
print-log:
|
||||||
|
go run main.go --logs
|
||||||
|
|
||||||
|
.PHONY: unit-test
|
||||||
|
unit-test:
|
||||||
|
go test ./... -short
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: unit-test integration-test-all
|
||||||
|
|
||||||
|
# Generate all our auto-generated files (test list, cheatsheets, maybe other things in the future)
|
||||||
|
.PHONY: generate
|
||||||
|
generate:
|
||||||
|
go generate ./...
|
||||||
|
|
||||||
|
.PHONY: format
|
||||||
|
format:
|
||||||
|
gofumpt -l -w .
|
||||||
|
|
||||||
|
# For more details about integration test, see https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md.
|
||||||
|
.PHONY: integration-test-tui
|
||||||
|
integration-test-tui:
|
||||||
|
go run cmd/integration_test/main.go tui $(filter-out $@,$(MAKECMDGOALS))
|
||||||
|
|
||||||
|
.PHONY: integration-test-cli
|
||||||
|
integration-test-cli:
|
||||||
|
go run cmd/integration_test/main.go cli $(filter-out $@,$(MAKECMDGOALS))
|
||||||
|
|
||||||
|
.PHONY: integration-test-all
|
||||||
|
integration-test-all:
|
||||||
|
go test pkg/integration/clients/*.go
|
||||||
|
|
||||||
|
.PHONY: bump-gocui
|
||||||
|
bump-gocui:
|
||||||
|
scripts/bump_gocui.sh
|
||||||
|
|
||||||
|
.PHONY: bump-lazycore
|
||||||
|
bump-lazycore:
|
||||||
|
scripts/bump_lazycore.sh
|
||||||
|
|
||||||
|
.PHONY: record-demo
|
||||||
|
record-demo:
|
||||||
|
demo/record_demo.sh $(filter-out $@,$(MAKECMDGOALS))
|
||||||
|
|
||||||
|
.PHONY: vendor
|
||||||
|
vendor:
|
||||||
|
go mod vendor && go mod tidy
|
||||||
@@ -16,7 +16,7 @@ Usage:
|
|||||||
> go run cmd/integration_test/main.go cli [--slow] [--sandbox] <test1> <test2> ...
|
> go run cmd/integration_test/main.go cli [--slow] [--sandbox] <test1> <test2> ...
|
||||||
If you pass no test names, it runs all tests
|
If you pass no test names, it runs all tests
|
||||||
Accepted environment variables:
|
Accepted environment variables:
|
||||||
KEY_PRESS_DELAY (e.g. 200): the number of milliseconds to wait between keypresses
|
INPUT_DELAY (e.g. 200): the number of milliseconds to wait between keypresses or mouse clicks
|
||||||
|
|
||||||
TUI mode:
|
TUI mode:
|
||||||
> go run cmd/integration_test/main.go tui
|
> go run cmd/integration_test/main.go tui
|
||||||
@@ -26,6 +26,29 @@ Usage:
|
|||||||
> go run cmd/integration_test/main.go help
|
> go run cmd/integration_test/main.go help
|
||||||
`
|
`
|
||||||
|
|
||||||
|
type flagInfo struct {
|
||||||
|
name string // name of the flag; can be used with "-" or "--"
|
||||||
|
flag *bool // a pointer to the variable that should be set to true when this flag is passed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes the args that you want to parse (excluding the program name and any
|
||||||
|
// subcommands), and returns the remaining args with the flags removed
|
||||||
|
func parseFlags(args []string, flags []flagInfo) []string {
|
||||||
|
outer:
|
||||||
|
for len(args) > 0 {
|
||||||
|
for _, f := range flags {
|
||||||
|
if args[0] == "-"+f.name || args[0] == "--"+f.name {
|
||||||
|
*f.flag = true
|
||||||
|
args = args[1:]
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
log.Fatal(usage)
|
log.Fatal(usage)
|
||||||
@@ -35,23 +58,26 @@ func main() {
|
|||||||
case "help":
|
case "help":
|
||||||
fmt.Println(usage)
|
fmt.Println(usage)
|
||||||
case "cli":
|
case "cli":
|
||||||
testNames := os.Args[2:]
|
|
||||||
slow := false
|
slow := false
|
||||||
sandbox := false
|
sandbox := false
|
||||||
// get the next arg if it's --slow
|
waitForDebugger := false
|
||||||
if len(os.Args) > 2 {
|
raceDetector := false
|
||||||
if os.Args[2] == "--slow" || os.Args[2] == "-slow" {
|
testNames := parseFlags(os.Args[2:], []flagInfo{
|
||||||
testNames = os.Args[3:]
|
{"slow", &slow},
|
||||||
slow = true
|
{"sandbox", &sandbox},
|
||||||
} else if os.Args[2] == "--sandbox" || os.Args[2] == "-sandbox" {
|
{"debug", &waitForDebugger},
|
||||||
testNames = os.Args[3:]
|
{"race", &raceDetector},
|
||||||
sandbox = true
|
})
|
||||||
}
|
clients.RunCLI(testNames, slow, sandbox, waitForDebugger, raceDetector)
|
||||||
}
|
|
||||||
|
|
||||||
clients.RunCLI(testNames, slow, sandbox)
|
|
||||||
case "tui":
|
case "tui":
|
||||||
clients.RunTUI()
|
raceDetector := false
|
||||||
|
remainingArgs := parseFlags(os.Args[2:], []flagInfo{
|
||||||
|
{"race", &raceDetector},
|
||||||
|
})
|
||||||
|
if len(remainingArgs) > 0 {
|
||||||
|
log.Fatal("tui only supports the -race argument.")
|
||||||
|
}
|
||||||
|
clients.RunTUI(raceDetector)
|
||||||
default:
|
default:
|
||||||
log.Fatal(usage)
|
log.Fatal(usage)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
This directory contains stuff for recording lazygit demos.
|
||||||
|
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
# Specify a command to be executed
|
||||||
|
# like `/bin/bash -l`, `ls`, or any other commands
|
||||||
|
# the default is bash for Linux
|
||||||
|
# or powershell.exe for Windows
|
||||||
|
command: echo "YOU NEED TO SPECIFY YOUR OWN COMMAND WITH THE -d ARG"
|
||||||
|
|
||||||
|
# Specify the current working directory path
|
||||||
|
# the default is the current working directory path
|
||||||
|
cwd: null
|
||||||
|
|
||||||
|
# Export additional ENV variables
|
||||||
|
env:
|
||||||
|
recording: true
|
||||||
|
|
||||||
|
# Explicitly set the number of columns
|
||||||
|
# or use `auto` to take the current
|
||||||
|
# number of columns of your shell
|
||||||
|
cols: 120 # 100
|
||||||
|
|
||||||
|
# Explicitly set the number of rows
|
||||||
|
# or use `auto` to take the current
|
||||||
|
# number of rows of your shell
|
||||||
|
rows: 35 # 30
|
||||||
|
|
||||||
|
# Amount of times to repeat GIF
|
||||||
|
# If value is -1, play once
|
||||||
|
# If value is 0, loop indefinitely
|
||||||
|
# If value is a positive number, loop n times
|
||||||
|
repeat: 0
|
||||||
|
|
||||||
|
# Quality
|
||||||
|
# 1 - 100
|
||||||
|
# Higher quality seems to make no difference, but running it through
|
||||||
|
# gifsicle ends up with a much better compressed version.
|
||||||
|
quality: 100
|
||||||
|
|
||||||
|
# Delay between frames in ms
|
||||||
|
# If the value is `auto` use the actual recording delays
|
||||||
|
frameDelay: auto
|
||||||
|
|
||||||
|
# Maximum delay between frames in ms
|
||||||
|
# Ignored if the `frameDelay` isn't set to `auto`
|
||||||
|
# Set to `auto` to prevent limiting the max idle time
|
||||||
|
maxIdleTime: 2000
|
||||||
|
|
||||||
|
# The surrounding frame box
|
||||||
|
# The `type` can be null, window, floating, or solid`
|
||||||
|
# To hide the title use the value null
|
||||||
|
# Don't forget to add a backgroundColor style with a null as type
|
||||||
|
frameBox:
|
||||||
|
type: floating
|
||||||
|
title: Lazygit
|
||||||
|
style:
|
||||||
|
border: 0px black solid
|
||||||
|
backgroundColor: "#1d1d1d"
|
||||||
|
margin: -5px
|
||||||
|
|
||||||
|
# Add a watermark image to the rendered gif
|
||||||
|
# You need to specify an absolute path for
|
||||||
|
# the image on your machine or a URL, and you can also
|
||||||
|
# add your own CSS styles
|
||||||
|
watermark:
|
||||||
|
imagePath: null
|
||||||
|
style:
|
||||||
|
position: absolute
|
||||||
|
right: 15px
|
||||||
|
bottom: 15px
|
||||||
|
width: 100px
|
||||||
|
opacity: 0.9
|
||||||
|
|
||||||
|
# Cursor style can be one of
|
||||||
|
# `block`, `underline`, or `bar`
|
||||||
|
cursorStyle: block
|
||||||
|
|
||||||
|
# Font family
|
||||||
|
# You can use any font that is installed on your machine
|
||||||
|
# in CSS-like syntax
|
||||||
|
# Download from:
|
||||||
|
# https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/DejaVuSansMono.zip
|
||||||
|
# Not using the mono font because it makes icons too small.
|
||||||
|
fontFamily: "DejaVuSansM Nerd Font"
|
||||||
|
|
||||||
|
# The size of the font
|
||||||
|
fontSize: 8
|
||||||
|
|
||||||
|
# The height of lines
|
||||||
|
lineHeight: 1
|
||||||
|
|
||||||
|
# The spacing between letters
|
||||||
|
letterSpacing: 0
|
||||||
|
|
||||||
|
# Theme
|
||||||
|
theme:
|
||||||
|
background: "transparent"
|
||||||
|
foreground: "#dddad6"
|
||||||
|
cursor: "#c7c7c7"
|
||||||
|
black: "#7a7a7a"
|
||||||
|
red: "#fc4384"
|
||||||
|
green: "#b3e33b"
|
||||||
|
yellow: "#ffa727"
|
||||||
|
blue: "#102895"
|
||||||
|
magenta: "#c930c7"
|
||||||
|
cyan: "#00c5c7"
|
||||||
|
white: "#c7c7c7"
|
||||||
|
brightBlack: "#676767"
|
||||||
|
brightRed: "#ff7fac"
|
||||||
|
brightGreen: "#c8ed71"
|
||||||
|
brightYellow: "#ebdf86"
|
||||||
|
brightBlue: "#6871ff"
|
||||||
|
brightMagenta: "#ff76ff"
|
||||||
|
brightCyan: "#5ffdff"
|
||||||
|
brightWhite: "#fffefe"
|
||||||
Executable
+81
@@ -0,0 +1,81 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TYPE=$1
|
||||||
|
TEST=$2
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 [gif|mp4] <test path>"
|
||||||
|
echo "e.g. using full path: $0 gif pkg/integration/tests/demo/nuke_working_tree.go"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$#" -ne 2 ]
|
||||||
|
then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$TYPE" != "gif" ] && [ "$TYPE" != "mp4" ]
|
||||||
|
then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$TEST" ]
|
||||||
|
then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORKTREE_PATH=$(git worktree list | grep assets | awk '{print $1}')
|
||||||
|
|
||||||
|
if [ -z "$WORKTREE_PATH" ]
|
||||||
|
then
|
||||||
|
echo "Could not find assets worktree. You'll need to create a worktree for the assets branch using the following command:"
|
||||||
|
echo "git worktree add .worktrees/assets assets"
|
||||||
|
echo "The assets branch has no shared history with the main branch: it exists to store assets which are too large to store in the main branch."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT_DIR="$WORKTREE_PATH/demo"
|
||||||
|
|
||||||
|
if ! command -v terminalizer &> /dev/null
|
||||||
|
then
|
||||||
|
echo "terminalizer could not be found"
|
||||||
|
echo "Install it with: npm install -g terminalizer"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v "gifsicle" &> /dev/null
|
||||||
|
then
|
||||||
|
echo "gifsicle could not be found"
|
||||||
|
echo "Install it with: npm install -g gifsicle"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get last part of the test path and set that as the output name
|
||||||
|
# example test path: pkg/integration/tests/01_basic_test.go
|
||||||
|
# For that we want: NAME=01_basic_test
|
||||||
|
NAME=$(echo "$TEST" | sed -e 's/.*\///' | sed -e 's/\..*//')
|
||||||
|
|
||||||
|
# Add the demo to the tests list (if missing) so that it can be run
|
||||||
|
go generate pkg/integration/tests/tests.go
|
||||||
|
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
|
||||||
|
# First we record the demo into a yaml representation
|
||||||
|
terminalizer -c demo/config.yml record --skip-sharing -d "go run cmd/integration_test/main.go cli --slow $TEST" "$OUTPUT_DIR/$NAME"
|
||||||
|
# Then we render it into a gif
|
||||||
|
terminalizer render "$OUTPUT_DIR/$NAME" -o "$OUTPUT_DIR/$NAME.gif"
|
||||||
|
|
||||||
|
# Then we convert it to either an mp4 or gif based on the command line argument
|
||||||
|
if [ "$TYPE" = "mp4" ]
|
||||||
|
then
|
||||||
|
COMPRESSED_PATH="$OUTPUT_DIR/$NAME.mp4"
|
||||||
|
ffmpeg -y -i "$OUTPUT_DIR/$NAME.gif" -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" "$COMPRESSED_PATH"
|
||||||
|
else
|
||||||
|
COMPRESSED_PATH="$OUTPUT_DIR/$NAME-compressed.gif"
|
||||||
|
gifsicle --colors 256 --use-col=web -O3 < "$OUTPUT_DIR/$NAME.gif" > "$COMPRESSED_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Demo recorded to $COMPRESSED_PATH"
|
||||||
+88
-66
@@ -3,7 +3,7 @@
|
|||||||
Default path for the config file:
|
Default path for the config file:
|
||||||
|
|
||||||
- Linux: `~/.config/lazygit/config.yml`
|
- Linux: `~/.config/lazygit/config.yml`
|
||||||
- MacOS: `~/Library/Application Support/lazygit/config.yml`
|
- MacOS: `~/Library/Application\ Support/lazygit/config.yml`
|
||||||
- Windows: `%APPDATA%\lazygit\config.yml`
|
- Windows: `%APPDATA%\lazygit\config.yml`
|
||||||
|
|
||||||
For old installations (slightly embarrassing: I didn't realise at the time that you didn't need to supply a vendor name to the path so I just used my name):
|
For old installations (slightly embarrassing: I didn't realise at the time that you didn't need to supply a vendor name to the path so I just used my name):
|
||||||
@@ -16,6 +16,17 @@ If you want to change the config directory:
|
|||||||
|
|
||||||
- MacOS: `export XDG_CONFIG_HOME="$HOME/.config"`
|
- MacOS: `export XDG_CONFIG_HOME="$HOME/.config"`
|
||||||
|
|
||||||
|
JSON schema is available for `config.yml` so that IntelliSense in Visual Studio Code (completion and error checking) is automatically enabled when the [YAML Red Hat][yaml] extension is installed. However, note that automatic schema detection only works if your config file is in one of the standard paths mentioned above. If you override the path to the file, you can still make IntelliSense work by adding
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# yaml-language-server: $schema=https://json.schemastore.org/lazygit.json
|
||||||
|
```
|
||||||
|
|
||||||
|
to the top of your config file or via [Visual Studio Code settings.json config][settings].
|
||||||
|
|
||||||
|
[yaml]: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml
|
||||||
|
[settings]: https://github.com/redhat-developer/vscode-yaml#associating-a-schema-to-a-glob-pattern-via-yamlschemas
|
||||||
|
|
||||||
## Default
|
## Default
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -24,10 +35,13 @@ gui:
|
|||||||
windowSize: 'normal' # one of 'normal' | 'half' | 'full' default is 'normal'
|
windowSize: 'normal' # one of 'normal' | 'half' | 'full' default is 'normal'
|
||||||
scrollHeight: 2 # how many lines you scroll by
|
scrollHeight: 2 # how many lines you scroll by
|
||||||
scrollPastBottom: true # enable scrolling past the bottom
|
scrollPastBottom: true # enable scrolling past the bottom
|
||||||
|
scrollOffMargin: 2 # how many lines to keep before/after the cursor when it reaches the top/bottom of the view; see 'Scroll-off Margin' section below
|
||||||
|
scrollOffBehavior: 'margin' # one of 'margin' | 'jump'; see 'Scroll-off Margin' section below
|
||||||
sidePanelWidth: 0.3333 # number from 0 to 1
|
sidePanelWidth: 0.3333 # number from 0 to 1
|
||||||
expandFocusedSidePanel: false
|
expandFocusedSidePanel: false
|
||||||
mainPanelSplitMode: 'flexible' # one of 'horizontal' | 'flexible' | 'vertical'
|
mainPanelSplitMode: 'flexible' # one of 'horizontal' | 'flexible' | 'vertical'
|
||||||
language: 'auto' # one of 'auto' | 'en' | 'zh' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru'
|
enlargedSideViewLocation: 'left' # one of 'left' | 'top'
|
||||||
|
language: 'auto' # one of 'auto' | 'en' | 'zh-CN' | 'zh-TW' | 'pl' | 'nl' | 'ja' | 'ko' | 'ru'
|
||||||
timeFormat: '02 Jan 06' # https://pkg.go.dev/time#Time.Format
|
timeFormat: '02 Jan 06' # https://pkg.go.dev/time#Time.Format
|
||||||
shortTimeFormat: '3:04PM'
|
shortTimeFormat: '3:04PM'
|
||||||
theme:
|
theme:
|
||||||
@@ -43,8 +57,6 @@ gui:
|
|||||||
- blue
|
- blue
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- blue # set to `default` to have no background colour
|
- blue # set to `default` to have no background colour
|
||||||
selectedRangeBgColor:
|
|
||||||
- blue
|
|
||||||
cherryPickedCommitBgColor:
|
cherryPickedCommitBgColor:
|
||||||
- cyan
|
- cyan
|
||||||
cherryPickedCommitFgColor:
|
cherryPickedCommitFgColor:
|
||||||
@@ -62,15 +74,18 @@ gui:
|
|||||||
showListFooter: true # for seeing the '5 of 20' message in list panels
|
showListFooter: true # for seeing the '5 of 20' message in list panels
|
||||||
showRandomTip: true
|
showRandomTip: true
|
||||||
showBranchCommitHash: false # show commit hashes alongside branch names
|
showBranchCommitHash: false # show commit hashes alongside branch names
|
||||||
experimentalShowBranchHeads: false # visualize branch heads with (*) in commits list
|
|
||||||
showBottomLine: true # for hiding the bottom information line (unless it has important information to tell you)
|
showBottomLine: true # for hiding the bottom information line (unless it has important information to tell you)
|
||||||
|
showPanelJumps: true # for showing the jump-to-panel keybindings as panel subtitles
|
||||||
showCommandLog: true
|
showCommandLog: true
|
||||||
showIcons: false # deprecated: use nerdFontsVersion instead
|
showIcons: false # deprecated: use nerdFontsVersion instead
|
||||||
nerdFontsVersion: "" # nerd fonts version to use ("2" or "3"); empty means don't show nerd font icons
|
nerdFontsVersion: "" # nerd fonts version to use ("2" or "3"); empty means don't show nerd font icons
|
||||||
|
showFileIcons: true # for hiding file icons in the file views
|
||||||
commandLogSize: 8
|
commandLogSize: 8
|
||||||
splitDiff: 'auto' # one of 'auto' | 'always'
|
splitDiff: 'auto' # one of 'auto' | 'always'
|
||||||
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
|
skipRewordInEditorWarning: false # for skipping the confirmation before launching the reword editor
|
||||||
border: 'single' # one of 'single' | 'double' | 'rounded' | 'hidden'
|
border: 'rounded' # one of 'single' | 'double' | 'rounded' | 'hidden'
|
||||||
|
animateExplosion: true # shows an explosion animation when nuking the working tree
|
||||||
|
portraitMode: 'auto' # one of 'auto' | 'never' | 'always'
|
||||||
git:
|
git:
|
||||||
paging:
|
paging:
|
||||||
colorArg: always
|
colorArg: always
|
||||||
@@ -104,8 +119,8 @@ git:
|
|||||||
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
|
overrideGpg: false # prevents lazygit from spawning a separate process when using GPG
|
||||||
disableForcePushing: false
|
disableForcePushing: false
|
||||||
parseEmoji: false
|
parseEmoji: false
|
||||||
diffContextSize: 3 # how many lines of context are shown around a change in diffs
|
|
||||||
os:
|
os:
|
||||||
|
copyToClipboardCmd: '' # See 'Custom Command for Copying to Clipboard' section
|
||||||
editPreset: '' # see 'Configuring File Editing' section
|
editPreset: '' # see 'Configuring File Editing' section
|
||||||
edit: ''
|
edit: ''
|
||||||
editAtLine: ''
|
editAtLine: ''
|
||||||
@@ -148,7 +163,7 @@ keybinding:
|
|||||||
jumpToBlock: ['1', '2', '3', '4', '5'] # goto the Nth block / panel
|
jumpToBlock: ['1', '2', '3', '4', '5'] # goto the Nth block / panel
|
||||||
nextMatch: 'n'
|
nextMatch: 'n'
|
||||||
prevMatch: 'N'
|
prevMatch: 'N'
|
||||||
optionMenu: null # show help menu
|
optionMenu: <disabled> # show help menu
|
||||||
optionMenu-alt1: '?' # show help menu
|
optionMenu-alt1: '?' # show help menu
|
||||||
select: '<space>'
|
select: '<space>'
|
||||||
goInto: '<enter>'
|
goInto: '<enter>'
|
||||||
@@ -185,20 +200,25 @@ keybinding:
|
|||||||
toggleWhitespaceInDiffView: '<c-w>'
|
toggleWhitespaceInDiffView: '<c-w>'
|
||||||
increaseContextInDiffView: '}'
|
increaseContextInDiffView: '}'
|
||||||
decreaseContextInDiffView: '{'
|
decreaseContextInDiffView: '{'
|
||||||
|
toggleRangeSelect: 'v'
|
||||||
|
rangeSelectUp: '<s-up>'
|
||||||
|
rangeSelectDown: '<s-down>'
|
||||||
status:
|
status:
|
||||||
checkForUpdate: 'u'
|
checkForUpdate: 'u'
|
||||||
recentRepos: '<enter>'
|
recentRepos: '<enter>'
|
||||||
files:
|
files:
|
||||||
commitChanges: 'c'
|
commit: 'c'
|
||||||
commitChangesWithoutHook: 'w' # commit changes without pre-commit hook
|
commitWithoutHook: 'w' # commit changes without pre-commit hook
|
||||||
amendLastCommit: 'A'
|
amendLastCommit: 'A'
|
||||||
commitChangesWithEditor: 'C'
|
commitChangesWithEditor: 'C'
|
||||||
|
findBaseCommitForFixup: '<c-f>'
|
||||||
|
confirmDiscard: 'x'
|
||||||
ignoreFile: 'i'
|
ignoreFile: 'i'
|
||||||
refreshFiles: 'r'
|
refreshFiles: 'r'
|
||||||
stashAllChanges: 's'
|
stash: 's'
|
||||||
viewStashOptions: 'S'
|
viewStashOptions: 'S'
|
||||||
toggleStagedAll: 'a' # stage/unstage all
|
toggleStagedAll: 'a' # stage/unstage all
|
||||||
viewResetOptions: 'D'
|
reset: 'D'
|
||||||
fetch: 'f'
|
fetch: 'f'
|
||||||
toggleTreeView: '`'
|
toggleTreeView: '`'
|
||||||
openMergeTool: 'M'
|
openMergeTool: 'M'
|
||||||
@@ -210,31 +230,31 @@ keybinding:
|
|||||||
forceCheckoutBranch: 'F'
|
forceCheckoutBranch: 'F'
|
||||||
rebaseBranch: 'r'
|
rebaseBranch: 'r'
|
||||||
renameBranch: 'R'
|
renameBranch: 'R'
|
||||||
mergeIntoCurrentBranch: 'M'
|
merge: 'M'
|
||||||
viewGitFlowOptions: 'i'
|
viewGitFlowOptions: 'i'
|
||||||
fastForward: 'f' # fast-forward this branch from its upstream
|
fastForward: 'f' # fast-forward this branch from its upstream
|
||||||
createTag: 'T'
|
newTag: 'T'
|
||||||
pushTag: 'P'
|
pushTag: 'P'
|
||||||
setUpstream: 'u' # set as upstream of checked-out branch
|
setUpstream: 'u' # set as upstream of checked-out branch
|
||||||
fetchRemote: 'f'
|
fetch: 'f'
|
||||||
commits:
|
commits:
|
||||||
squashDown: 's'
|
squash: 's'
|
||||||
renameCommit: 'r'
|
reword: 'r'
|
||||||
renameCommitWithEditor: 'R'
|
rewordWithEditor: 'R'
|
||||||
viewResetOptions: 'g'
|
viewResetOptions: 'g'
|
||||||
markCommitAsFixup: 'f'
|
fixup: 'f'
|
||||||
createFixupCommit: 'F' # create fixup commit for this commit
|
createFixupCommit: 'F' # create fixup commit for this commit
|
||||||
squashAboveCommits: 'S'
|
applyFixupCommits: 'S'
|
||||||
moveDownCommit: '<c-j>' # move commit down one
|
moveDownCommit: '<c-j>' # move commit down one
|
||||||
moveUpCommit: '<c-k>' # move commit up one
|
moveUpCommit: '<c-k>' # move commit up one
|
||||||
amendToCommit: 'A'
|
amend: 'A'
|
||||||
pickCommit: 'p' # pick commit (when mid-rebase)
|
amendCommitAttribute: 'a'
|
||||||
revertCommit: 't'
|
pick: 'p' # pick commit (when mid-rebase)
|
||||||
cherryPickCopy: 'c'
|
revert: 't'
|
||||||
cherryPickCopyRange: 'C'
|
cherryPickCopy: 'C'
|
||||||
pasteCommits: 'v'
|
pasteCommits: 'V'
|
||||||
tagCommit: 'T'
|
tagCommit: 'T'
|
||||||
checkoutCommit: '<space>'
|
checkout: '<space>'
|
||||||
resetCherryPick: '<c-R>'
|
resetCherryPick: '<c-R>'
|
||||||
copyCommitMessageToClipboard: '<c-y>'
|
copyCommitMessageToClipboard: '<c-y>'
|
||||||
openLogMenu: '<c-l>'
|
openLogMenu: '<c-l>'
|
||||||
@@ -243,10 +263,8 @@ keybinding:
|
|||||||
popStash: 'g'
|
popStash: 'g'
|
||||||
renameStash: 'r'
|
renameStash: 'r'
|
||||||
commitFiles:
|
commitFiles:
|
||||||
checkoutCommitFile: 'c'
|
checkout: 'c'
|
||||||
main:
|
main:
|
||||||
toggleDragSelect: 'v'
|
|
||||||
toggleDragSelect-alt: 'V'
|
|
||||||
toggleSelectHunk: 'a'
|
toggleSelectHunk: 'a'
|
||||||
pickBothHunks: 'b'
|
pickBothHunks: 'b'
|
||||||
submodules:
|
submodules:
|
||||||
@@ -278,29 +296,36 @@ os:
|
|||||||
open: 'open {{filename}}'
|
open: 'open {{filename}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuring File Editing
|
## Custom Command for Copying to Clipboard
|
||||||
|
```yaml
|
||||||
|
os:
|
||||||
|
copyToClipboardCmd: ''
|
||||||
|
```
|
||||||
|
Specify an external command to invoke when copying to clipboard is requested. `{{text}` will be replaced by text to be copied. Default is to copy to system clipboard.
|
||||||
|
|
||||||
There are two commands for opening files, `o` for "open" and `e` for "edit". `o`
|
If you are working on a terminal that supports OSC52, the following command will let you take advantage of it:
|
||||||
acts as if the file was double-clicked in the Finder/Explorer, so it also works
|
```
|
||||||
for non-text files, whereas `e` opens the file in an editor. `e` can also jump
|
os:
|
||||||
to the right line in the file if you invoke it from the staging panel, for
|
copyToClipboardCmd: printf "\033]52;c;$(printf {{text}} | base64)\a" > /dev/tty
|
||||||
example.
|
```
|
||||||
|
|
||||||
To tell lazygit which editor to use for the `e` command, the easiest way to do
|
|
||||||
that is to provide an editPreset config, e.g.
|
## Configuring File Editing
|
||||||
|
|
||||||
|
There are two commands for opening files, `o` for "open" and `e` for "edit". `o` acts as if the file was double-clicked in the Finder/Explorer, so it also works for non-text files, whereas `e` opens the file in an editor. `e` can also jump to the right line in the file if you invoke it from the staging panel, for example.
|
||||||
|
|
||||||
|
To tell lazygit which editor to use for the `e` command, the easiest way to do that is to provide an editPreset config, e.g.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
os:
|
os:
|
||||||
editPreset: 'vscode'
|
editPreset: 'vscode'
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported presets are `vim`, `nvim`, `emacs`, `nano`, `vscode`, `sublime`, `bbedit`,
|
Supported presets are `vim`, `nvim`, `nvim-remote`, `lvim`, `emacs`, `nano`, `micro`, `vscode`, `sublime`, `bbedit`, `kakoune`, `helix`, and `xcode`. In many cases lazygit will be able to guess the right preset from your $(git config core.editor), or an environment variable such as $VISUAL or $EDITOR.
|
||||||
`kakoune`, `helix`, and `xcode`. In many cases lazygit will be able to guess the right preset
|
|
||||||
from your $(git config core.editor), or an environment variable such as $VISUAL or $EDITOR.
|
|
||||||
|
|
||||||
If for some reason you are not happy with the default commands from a preset, or
|
`nvim-remote` is an experimental preset for when you have invoked lazygit from within a neovim process, allowing lazygit to open the file from within the parent process rather than spawning a new one.
|
||||||
there simply is no preset for your editor, you can customize the commands by
|
|
||||||
setting the `edit`, `editAtLine`, and `editAtLineAndWait` options, e.g.:
|
If for some reason you are not happy with the default commands from a preset, or there simply is no preset for your editor, you can customize the commands by setting the `edit`, `editAtLine`, and `editAtLineAndWait` options, e.g.:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
os:
|
os:
|
||||||
@@ -308,15 +333,14 @@ os:
|
|||||||
editAtLine: 'myeditor --line={{line}} {{filename}}'
|
editAtLine: 'myeditor --line={{line}} {{filename}}'
|
||||||
editAtLineAndWait: 'myeditor --block --line={{line}} {{filename}}'
|
editAtLineAndWait: 'myeditor --block --line={{line}} {{filename}}'
|
||||||
editInTerminal: true
|
editInTerminal: true
|
||||||
|
openDirInEditor: 'myeditor {{dir}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
The `editInTerminal` option is used to decide whether lazygit needs to suspend
|
The `editInTerminal` option is used to decide whether lazygit needs to suspend itself to the background before calling the editor. It should really be named `suspend` because for some cases like when lazygit is opened from within a neovim session and you're using the `nvim-remote` preset, you're technically still in a terminal. Nonetheless we're sticking with the name `editInTerminal` for backwards compatibility.
|
||||||
itself to the background before calling the editor.
|
|
||||||
|
|
||||||
Contributions of new editor presets are welcome; see the `getPreset` function in
|
Contributions of new editor presets are welcome; see the `getPreset` function in [`editor_presets.go`](https://github.com/jesseduffield/lazygit/blob/master/pkg/config/editor_presets.go).
|
||||||
[`editor_presets.go`](https://github.com/jesseduffield/lazygit/blob/master/pkg/config/editor_presets.go).
|
|
||||||
|
|
||||||
### Overriding default config file location
|
## Overriding default config file location
|
||||||
|
|
||||||
To override the default config directory, use `CONFIG_DIR="$HOME/.config/lazygit"`. This directory contains the config file in addition to some other files lazygit uses to keep track of state across sessions.
|
To override the default config directory, use `CONFIG_DIR="$HOME/.config/lazygit"`. This directory contains the config file in addition to some other files lazygit uses to keep track of state across sessions.
|
||||||
|
|
||||||
@@ -330,6 +354,14 @@ or
|
|||||||
LG_CONFIG_FILE="$HOME/.base_lg_conf,$HOME/.light_theme_lg_conf" lazygit
|
LG_CONFIG_FILE="$HOME/.base_lg_conf,$HOME/.light_theme_lg_conf" lazygit
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Scroll-off Margin
|
||||||
|
|
||||||
|
When the selected line gets close to the bottom of the window and you hit down-arrow, there's a feature called "scroll-off margin" that lets the view scroll a little earlier so that you can see a bit of what's coming in the direction that you are moving. This is controlled by the `gui.scrollOffMargin` setting (default: 2), so it keeps 2 lines below the selection visible as you scroll down. It can be set to 0 to scroll only when the selection reaches the bottom of the window.
|
||||||
|
|
||||||
|
That's the behavior when `gui.scrollOffBehavior` is set to "margin" (the default). If you set `gui.scrollOffBehavior` to "jump", then upon reaching the last line of a view and hitting down-arrow the view will scroll by half a page so that the selection ends up in the middle of the view. This may feel a little jarring because the cursor jumps around when continuously moving down, but it has the advantage that the view doesn't scroll as often.
|
||||||
|
|
||||||
|
This setting applies both to all list views (e.g. commits and branches etc), and to the staging view.
|
||||||
|
|
||||||
## Color Attributes
|
## Color Attributes
|
||||||
|
|
||||||
For color attributes you can choose an array of attributes (with max one color attribute)
|
For color attributes you can choose an array of attributes (with max one color attribute)
|
||||||
@@ -357,15 +389,13 @@ The available attributes are:
|
|||||||
|
|
||||||
## Highlighting the selected line
|
## Highlighting the selected line
|
||||||
|
|
||||||
If you don't like the default behaviour of highlighting the selected line with a blue background, you can use the `selectedLineBgColor` and `selectedRangeBgColor` keys to customise the behaviour. If you just want to embolden the selected line (this was the original default), you can do the following:
|
If you don't like the default behaviour of highlighting the selected line with a blue background, you can use the `selectedLineBgColor` key to customise the behaviour. If you just want to embolden the selected line (this was the original default), you can do the following:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
gui:
|
gui:
|
||||||
theme:
|
theme:
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- default
|
- default
|
||||||
selectedRangeBgColor:
|
|
||||||
- default
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use the reverse attribute like so:
|
You can also use the reverse attribute like so:
|
||||||
@@ -375,8 +405,6 @@ gui:
|
|||||||
theme:
|
theme:
|
||||||
selectedLineBgColor:
|
selectedLineBgColor:
|
||||||
- reverse
|
- reverse
|
||||||
selectedRangeBgColor:
|
|
||||||
- reverse
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Custom Author Color
|
## Custom Author Color
|
||||||
@@ -426,19 +454,18 @@ gui:
|
|||||||
nerdFontsVersion: "3"
|
nerdFontsVersion: "3"
|
||||||
```
|
```
|
||||||
|
|
||||||
Supported versions are "2" and "3". The deprecated config `showIcons` sets the
|
Supported versions are "2" and "3". The deprecated config `showIcons` sets the version to "2" for backwards compatibility.
|
||||||
version to "2" for backwards compatibility.
|
|
||||||
|
|
||||||
## Keybindings
|
## Keybindings
|
||||||
|
|
||||||
For all possible keybinding options, check [Custom_Keybindings.md](https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md)
|
For all possible keybinding options, check [Custom_Keybindings.md](https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md)
|
||||||
|
|
||||||
You can disable certain key bindings by specifying `null`.
|
You can disable certain key bindings by specifying `<disabled>`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
keybinding:
|
keybinding:
|
||||||
universal:
|
universal:
|
||||||
edit: null # disable 'edit file'
|
edit: <disabled> # disable 'edit file'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example Keybindings For Colemak Users
|
### Example Keybindings For Colemak Users
|
||||||
@@ -475,9 +502,7 @@ keybinding:
|
|||||||
|
|
||||||
## Custom pull request URLs
|
## Custom pull request URLs
|
||||||
|
|
||||||
Some git provider setups (e.g. on-premises GitLab) can have distinct URLs for git-related calls and
|
Some git provider setups (e.g. on-premises GitLab) can have distinct URLs for git-related calls and the web interface/API itself. To work with those, Lazygit needs to know where it needs to create the pull request. You can do so on your `config.yml` file using the following syntax:
|
||||||
the web interface/API itself. To work with those, Lazygit needs to know where it needs to create
|
|
||||||
the pull request. You can do so on your `config.yml` file using the following syntax:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
@@ -492,8 +517,7 @@ Where:
|
|||||||
|
|
||||||
## Predefined commit message prefix
|
## Predefined commit message prefix
|
||||||
|
|
||||||
In situations where certain naming pattern is used for branches and commits, pattern can be used to populate
|
In situations where certain naming pattern is used for branches and commits, pattern can be used to populate commit message with prefix that is parsed from the branch name.
|
||||||
commit message with prefix that is parsed from the branch name.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -523,9 +547,7 @@ Result:
|
|||||||
|
|
||||||
## Launching not in a repository behaviour
|
## Launching not in a repository behaviour
|
||||||
|
|
||||||
By default, when launching lazygit from a directory that is not a repository,
|
By default, when launching lazygit from a directory that is not a repository, you will be prompted to choose if you would like to initialize a repo. You can override this behaviour in the config with one of the following:
|
||||||
you will be prompted to choose if you would like to initialize a repo. You can
|
|
||||||
override this behaviour in the config with one of the following:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# for default prompting behaviour
|
# for default prompting behaviour
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ The permitted contexts are:
|
|||||||
| -------------- | -------------------------------------------------------------------------------------------------------- |
|
| -------------- | -------------------------------------------------------------------------------------------------------- |
|
||||||
| status | The 'Status' tab |
|
| status | The 'Status' tab |
|
||||||
| files | The 'Files' tab |
|
| files | The 'Files' tab |
|
||||||
|
| worktrees | The 'Worktrees' tab |
|
||||||
| localBranches | The 'Local Branches' tab |
|
| localBranches | The 'Local Branches' tab |
|
||||||
| remotes | The 'Remotes' tab |
|
| remotes | The 'Remotes' tab |
|
||||||
| remoteBranches | The context you get when pressing enter on a remote in the remotes tab |
|
| remoteBranches | The context you get when pressing enter on a remote in the remotes tab |
|
||||||
@@ -300,6 +301,7 @@ SelectedRemote
|
|||||||
SelectedTag
|
SelectedTag
|
||||||
SelectedStashEntry
|
SelectedStashEntry
|
||||||
SelectedCommitFile
|
SelectedCommitFile
|
||||||
|
SelectedWorktree
|
||||||
CheckedOutBranch
|
CheckedOutBranch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+23
-1
@@ -1,6 +1,6 @@
|
|||||||
# Custom Pagers
|
# Custom Pagers
|
||||||
|
|
||||||
Lazygit supports custom pagers, [configured](/docs/Config.md) in the config.yml file (which can be opened by pressing `o` in the Status panel).
|
Lazygit supports custom pagers, [configured](/docs/Config.md) in the config.yml file (which can be opened by pressing `e` in the Status panel).
|
||||||
|
|
||||||
Support does not extend to Windows users, because we're making use of a package which doesn't have Windows support.
|
Support does not extend to Windows users, because we're making use of a package which doesn't have Windows support.
|
||||||
|
|
||||||
@@ -62,3 +62,25 @@ git:
|
|||||||
```
|
```
|
||||||
|
|
||||||
If you set `useConfig: true`, lazygit will use whatever pager is specified in `$GIT_PAGER`, `$PAGER`, or your *git config*. If the pager ends with something like ` | less` we will strip that part out, because less doesn't play nice with our rendering approach. If the custom pager uses less under the hood, that will also break rendering (hence the `--paging=never` flag for the `delta` pager).
|
If you set `useConfig: true`, lazygit will use whatever pager is specified in `$GIT_PAGER`, `$PAGER`, or your *git config*. If the pager ends with something like ` | less` we will strip that part out, because less doesn't play nice with our rendering approach. If the custom pager uses less under the hood, that will also break rendering (hence the `--paging=never` flag for the `delta` pager).
|
||||||
|
|
||||||
|
## Using external diff commands
|
||||||
|
|
||||||
|
Some diff tools can't work as a simple pager like the ones above do, because they need access to the entire diff, so just post-processing git's diff is not enough for them. The most notable example is probably [difftastic](https://difftastic.wilfred.me.uk).
|
||||||
|
|
||||||
|
These can be used in lazygit by using the `externalDiffCommand` config; in the case of difftastic, that could be
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
git:
|
||||||
|
paging:
|
||||||
|
externalDiffCommand: difft --color=always
|
||||||
|
```
|
||||||
|
|
||||||
|
The `colorArg`, `pager`, and `useConfig` options are not used in this case.
|
||||||
|
|
||||||
|
You can add whatever extra arguments you prefer for your difftool; for instance
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
git:
|
||||||
|
paging:
|
||||||
|
externalDiffCommand: difft --color=always --display=inline --syntax-highlight=off
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# Fixup Commits
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
There's this common scenario that you have a PR in review, the reviewer is
|
||||||
|
requesting some changes, and you make those changes and would normally simply
|
||||||
|
squash them into the original commit that they came from. If you do that,
|
||||||
|
however, there's no way for the reviewer to see what you changed. You could just
|
||||||
|
make a separate commit with those changes at the end of the branch, but this is
|
||||||
|
not ideal because it results in a git history that is not very clean.
|
||||||
|
|
||||||
|
To help with this, git has a concept of fixup commits: you do make a separate
|
||||||
|
commit, but the subject of this commit is the string "fixup! " followed by the
|
||||||
|
original commit subject. This both tells the reviewer what's going on (you are
|
||||||
|
making a change that you later will squash into the designated commit), and it
|
||||||
|
provides an easy way to actually perform this squash operation when you are
|
||||||
|
ready to do that (before merging).
|
||||||
|
|
||||||
|
## Creating fixup commits
|
||||||
|
|
||||||
|
You could of course create fixup commits manually by typing in the commit
|
||||||
|
message with the prefix yourself. But lazygit has an easier way to do that:
|
||||||
|
in the Commits view, select the commit that you want to create a fixup for, and
|
||||||
|
press shift-F (for "Create fixup commit for this commit"). This automatically
|
||||||
|
creates a commit with the appropriate subject line.
|
||||||
|
|
||||||
|
Don't confuse this with the lowercase "f" command ("Fixup commit"); that one
|
||||||
|
squashes the selected commit into its parent, this is not what we want here.
|
||||||
|
|
||||||
|
## Squashing fixup commits
|
||||||
|
|
||||||
|
When you're ready to merge the branch and want to squash all these fixup commits
|
||||||
|
that you created, that's very easy to do: select the first commit of your branch
|
||||||
|
and hit shift-S (for "Squash all 'fixup!' commits above selected commit
|
||||||
|
(autosquash)"). Boom, done.
|
||||||
|
|
||||||
|
## Finding the commit to create a fixup for
|
||||||
|
|
||||||
|
When you are making changes to code that you changed earlier in a long branch,
|
||||||
|
it can be tedious to find the commit to squash it into. Lazygit has a command to
|
||||||
|
help you with this, too: in the Files view, press ctrl-f to select the right
|
||||||
|
base commit in the Commits view automatically. From there, you can either press
|
||||||
|
shift-F to create a fixup commit for it, or shift-A to amend your changes into
|
||||||
|
the commit if you haven't published your branch yet.
|
||||||
|
|
||||||
|
This command works in many cases, and when it does it almost feels like magic,
|
||||||
|
but it's important to understand its limitations because it doesn't always work.
|
||||||
|
The way it works is that it looks at the deleted lines of your current
|
||||||
|
modifications, blames them to find out which commit those lines come from, and
|
||||||
|
if they all come from the same commit, it selects it. So here are cases where it
|
||||||
|
doesn't work:
|
||||||
|
|
||||||
|
- Your current diff has only added lines, but no deleted lines. In this case
|
||||||
|
there's no way for lazygit to know which commit you want to add them to.
|
||||||
|
- The deleted lines belong to multiple different commits. In this case you can
|
||||||
|
help lazygit by staging a set of files or hunks that all belong to the same
|
||||||
|
commit; if some changes are staged, the ctrl-f command works only on those.
|
||||||
|
- The found commit is already on master; in this case, lazygit refuses to select
|
||||||
|
it, because it doesn't make sense to create fixups for it, let alone amend to
|
||||||
|
it.
|
||||||
|
|
||||||
|
To sum it up: the command works great if you are changing code again that you
|
||||||
|
changed or added earlier in the same branch. This is a common enough case to
|
||||||
|
make the command useful.
|
||||||
+3
-1
@@ -3,7 +3,9 @@
|
|||||||
* [Configuration](./Config.md).
|
* [Configuration](./Config.md).
|
||||||
* [Custom Commands](./Custom_Command_Keybindings.md)
|
* [Custom Commands](./Custom_Command_Keybindings.md)
|
||||||
* [Custom Pagers](./Custom_Pagers.md)
|
* [Custom Pagers](./Custom_Pagers.md)
|
||||||
|
* [Dev docs](./dev)
|
||||||
* [Keybindings](./keybindings)
|
* [Keybindings](./keybindings)
|
||||||
* [Undo/Redo](./Undoing.md)
|
* [Undo/Redo](./Undoing.md)
|
||||||
|
* [Range Select](./Range_Select.md)
|
||||||
* [Searching/Filtering](./Searching.md)
|
* [Searching/Filtering](./Searching.md)
|
||||||
* [Dev docs](./dev)
|
* [Stacked Branches](./Stacked_Branches.md)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Range Select
|
||||||
|
|
||||||
|
Some actions can be performed on a range of contiguous items. For example:
|
||||||
|
* staging multiple files at once
|
||||||
|
* squashing multiple commits at once
|
||||||
|
* copying (for cherry-pick) multiple commits at once
|
||||||
|
|
||||||
|
There are two ways to select a range of items:
|
||||||
|
1. Sticky range select: Press 'v' to toggle range select, then expand the selection using the up/down arrow key. To reset the selection, press 'v' again.
|
||||||
|
2. Non-sticky range select: Press shift+up or shift+down to expand the selection. To reset the selection, press up/down without shift.
|
||||||
|
|
||||||
|
The sticky option will be more familiar to vim users, and the second option will feel more natural to users who aren't used to doing things in a modal way.
|
||||||
|
|
||||||
|
In order to perform an action on a range of items, simply press the normal key for that action. If the action only works on individual items, it will raise an error. This is a new feature and the plan is to incrementally support range select for more and more actions. If there is an action you would like to support range select which currently does not, please raise an issue in the repo.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Working with stacked branches
|
||||||
|
|
||||||
|
When working on a large branch it can often be useful to break it down into
|
||||||
|
smaller pieces, and it can help to create separate branches for each independent
|
||||||
|
chunk of changes. For example, you could have one branch for preparatory
|
||||||
|
refactorings, one for backend changes, and one for frontend changes. Those
|
||||||
|
branches would then all be stacked onto each other.
|
||||||
|
|
||||||
|
Git has support for rebasing such a stack as a whole; you can enable it by
|
||||||
|
setting the git config `rebase.updateRefs` to true. If you then rebase the
|
||||||
|
topmost branch of the stack, the other ones in the stack will follow. This
|
||||||
|
includes interactive rebases, so for example amending a commit in the first
|
||||||
|
branch of the stack will "just work" in the sense that it keeps the other
|
||||||
|
branches properly stacked onto it.
|
||||||
|
|
||||||
|
Lazygit visualizes the invidual branch heads in the stack by marking them with a
|
||||||
|
cyan asterisk (or a cyan branch symbol if you are using [nerd
|
||||||
|
fonts](Config.md#display-nerd-fonts-icons)).
|
||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
# Undo/Redo in lazygit
|
# Undo/Redo in lazygit
|
||||||
|
|
||||||

|
You can undo the last action by pressing 'z' and redo with `ctrl+z`. Here we drop a couple of commits and then undo the actions.
|
||||||
|
Undo uses the reflog which is specific to commits and branches so we can't undo changes to the working tree or stash.
|
||||||
|
|
||||||
## Keybindings:
|

|
||||||
'z' to undo, 'ctrl+z' to redo
|
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# Lazygit Codebase Guide
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
* `pkg/app`: Contains startup code, inititalises a bunch of stuff like logging, the user config, etc, before starting the gui. Catches and handles some errors that the gui raises.
|
||||||
|
* `pkg/app/daemon`: Contains code relating to the lazygit daemon. This could be better named: it's is not a daemon in the sense that it's a long-running background process; rather it's a short-lived background process that we pass to git for certain tasks, like GIT_EDITOR for when we want to set the TODO file for an interactive rebase.
|
||||||
|
* `pkg/cheatsheet`: Generates the keybinding cheatsheets in `docs/keybindings`.
|
||||||
|
* `pkg/commands/git_commands`: All communication to the git binary happens here. So for example there's a `Checkout` method which calls `git checkout`.
|
||||||
|
* `pkg/commands/oscommands`: Contains code for talking to the OS, and for invoking commands in general
|
||||||
|
* `pkg/commands/git_config`: Reading of the git config all happens here.
|
||||||
|
* `pkg/commands/hosting_service`: Contains code that is specific to git hosting services (aka forges).
|
||||||
|
* `pkg/commands/models`: Contains model structs that represent commits, branches, files, etc.
|
||||||
|
* `pkg/commands/patch`: Contains code for parsing and working with git patches
|
||||||
|
* `pkg/common`: Contains the `Common` struct which holds common dependencies like the logger, i18n, and the user config. Most structs in the code will have a field named `c` which holds a common struct (or a derivative of the common struct).
|
||||||
|
* `pkg/config`: Contains code relating to the Lazygit user config. Specifically `pkg/config/user_config/go` defines the user config struct and its default values.
|
||||||
|
* `pkg/constants`: Contains some constant strings (e.g. links to docs)
|
||||||
|
* `pkg/env`: Contains code relating to setting/getting environment variables
|
||||||
|
* `pkg/i18n`: Contains internationalised strings
|
||||||
|
* `pkg/integration`: Contains end-to-end tests
|
||||||
|
* `pkg/jsonschema`: Contains generator for user config JSON schema.
|
||||||
|
* `pkg/logs`: Contains code for instantiating the logger and for tailing the logs via `lazygit --logs`
|
||||||
|
* `pkg/tasks`: Contains code for running asynchronous tasks: mostly related to efficiently rendering command output to the main window.
|
||||||
|
* `pkg/theme`: Contains code related to colour themes.
|
||||||
|
* `pkg/updates`: Contains code related to Lazygit updates (checking for update, download and installing the update)
|
||||||
|
* `pkg/utils`: Contains lots of low-level helper functions
|
||||||
|
* `pkg/gui`: Contains code related to the gui. We've still got a God Struct in the form of our Gui struct, but over time code has been moved out into contexts, controllers, and helpers, and we intend to continue moving more code out over time.
|
||||||
|
* `pkg/gui/context`: Contains code relating to contexts. There is a context for each view e.g. a branches context, a tags context, etc. Contexts manage state related to the view and receive keypresses.
|
||||||
|
* `pkg/gui/controllers`: Contains code relating to controllers. Controllers define a list of keybindings and their associated handlers. One controller can be assigned to multiple contexts, and one context can contain multiple controllers.
|
||||||
|
* `pkg/gui/controllers/helpers`: Contains code that is shared between multiple controllers.
|
||||||
|
* `pkg/gui/filetree`: Contains code relating to the representation of filetrees.
|
||||||
|
* `pkg/gui/keybindings`: Contains code for mapping between keybindings and their labels
|
||||||
|
* `pkg/gui/mergeconflicts`: Contains code relating to the handling of merge conflicts
|
||||||
|
* `pkg/gui/modes`: Contains code relating to the state of different modes e.g. cherry picking mode, rebase mode.
|
||||||
|
* `pkg/gui/patch_exploring`: Contains code relating to the state of patch-oriented views like the staging view.
|
||||||
|
* `pkg/gui/popup`: Contains code that lets you easily raise popups
|
||||||
|
* `pkg/gui/presentation`: Contains presentation code i.e. code concerned with rendering content inside views
|
||||||
|
* `pkg/gui/services/custom_commands`: Contains code related to user-defined custom commands.
|
||||||
|
* `pkg/gui/status`: Contains code for invoking loaders and toasts
|
||||||
|
* `pkg/gui/style`: Contains code for specifying text styles (colour, bold, etc)
|
||||||
|
* `pkg/gui/types`: Contains various gui-specific types and interfaces. Lots of code lives here to avoid circular dependencies
|
||||||
|
* `vendor/github.com/jesseduffield/gocui`: Gocui is the underlying library used for handling the gui event loop, handling keypresses, and rendering the UI. It defines the View struct which our own context structs build upon.
|
||||||
|
|
||||||
|
## Important files
|
||||||
|
|
||||||
|
* `pkg/config/user_config.go`: defines the user config and default values
|
||||||
|
* `pkg/gui/keybindings.go`: defines keybindings which have not yet been moved into a controller (originally all keybindings were defined here)
|
||||||
|
* `pkg/gui/controllers.go`: links up controllers with contexts
|
||||||
|
* `pkg/gui/controllers/helpers/helpers.go`: defines all the different helper structs
|
||||||
|
* `pkg/commands/git.go`: defines all the different git command structs
|
||||||
|
* `pkg/gui/gui.go`: defines the top-level gui state and gui initialisation/run code
|
||||||
|
* `pkg/gui/layout.go`: defines what happens on each render
|
||||||
|
* `pkg/gui/controllers/helpers/window_arrangement_helper.go`: defines the layout of the UI and the size/position of each window
|
||||||
|
* `pkg/gui/context/context.go`: defines the different contexts
|
||||||
|
* `pkg/gui/context/setup.go`: defines initialisation code for all contexts
|
||||||
|
* `pkg/gui/context.go`: manages the lifecycle of contexts, the context stack, and focus changes.
|
||||||
|
* `pkg/gui/types/views.go`: defines views
|
||||||
|
* `pkg/gui/views.go`: defines the ordering of views (front to back) and their initialisation code
|
||||||
|
* `pkg/gui/gui_common.go`: defines gui-specific methods that all controllers and helpers have access to
|
||||||
|
* `pkg/i18n/english.go`: defines the set of i18n strings and their English values
|
||||||
|
* `pkg/gui/controllers/helpers/refresh_helper.go`: manages refreshing of models. The refresh helper is typically invoked at the end of an action to re-load affected models from git (e.g. re-load branches after doing a git pull)
|
||||||
|
* `pkg/gui/controllers/quit_actions.go`: contains code that runs when you hit 'escape' on a view (assuming the view doesn't define its own escape handler)
|
||||||
|
* `vendor/github.com/jesseduffield/gocui/gui.go`: defines the gocui gui struct
|
||||||
|
* `vendor/github.com/jesseduffield/gocui/view.go`: defines the gocui view struct
|
||||||
|
|
||||||
|
## Concepts
|
||||||
|
|
||||||
|
* **View**: Views are defined in the gocui package, and they maintain an internal buffer of content which is rendered each time the screen is drawn.
|
||||||
|
* **Context**: A context is tied to a view and contains some additional state and logic specific to that view e.g. the branches context has code relating specifically to branches, and writes the list of branches to the branches view. Views and contexts share some responsibilities for historical reasons.
|
||||||
|
* **Controller**: A controller defined keybindings with associated handlers. One controller can be assigned to multiple contexts and one context can have multiple controllers. For example the list controller handles keybindings relating to navigating a list, and is assigned to all list contexts (e.g. the branches context).
|
||||||
|
* **Helper**: A helper defines shared code used by controllers, or used by some other parts of the application. Often a controller will have a method that ends up needing to be used by another controller, so in that case we move the method out into a helper so that both controllers can use it. We need to do this because controllers cannot refer to other controllers' methods.
|
||||||
|
|
||||||
|
In terms of dependencies, controllers sit at the highest level, so they can refer to helpers, contexts, and views (although it's preferable for view-specific code to live in contexts). Helpers can refer to contexts and views, and contexts can only refer to views. Views can't refer to contexts, controllers, or helpers.
|
||||||
|
|
||||||
|
* **Window**: A window is a section of the screen which will render a view. Windows are named after the default view that appears there, so for example there is a 'stash' window that is so named because by default the stash view appears there. But if you press enter on a stash entry, the stash entry's files will be shown in a different view, but in the same window.
|
||||||
|
* **Panel**: The term 'panel' is still used in a few places to refer to either a view or a window, and it's a term that is now deprecated in favour of 'view' and 'window'.
|
||||||
|
* **Tab**: Each tab in a window (e.g. Files, Worktrees, Submodules) actually has a corresponding view which we bring to the front upon changing tabs.
|
||||||
|
* **Model**: Representation of a git object e.g. commits, branches, files.
|
||||||
|
* **ViewModel**: Used by a context to maintain state related to the view.
|
||||||
|
* **Keybinding**: A keybinding associates a _key_ with an _action_. For example if you press the 'down' arrow, the action performed will be your cursor moving down a list by one.
|
||||||
|
* **Action**: An action is the thing that happens when you press a key. Often an action will invoke a git command, but not always: for example, navigation actions don't involve git.
|
||||||
|
* **Common structs**: Most structs have a field named `c` which contains a 'common' struct: a struct containing a bag of dependencies that most structs of the same layer require. For example if you want to access a helper from a controller you can do so with `self.c.Helpers.MyHelper`.
|
||||||
|
|
||||||
|
## Event loop and threads
|
||||||
|
|
||||||
|
The event loop is managed in the `MainLoop` function of `vendor/github.com/jesseduffield/gocui/gui.go`. Any time there is an event like a key press or a window resize, the event will be processed and then the screen will be redrawn. This involves calling the `layout` function defined in `pkg/gui/layout.go`, which lays out the windows and invokes some on-render hooks.
|
||||||
|
|
||||||
|
Often, as part of handling a keypress, we'll want to run some code asynchronously so that it doesn't block the UI thread. For this we'll typically run `self.c.OnWorker(myFunc)`. If the worker wants to then do something on the UI thread again it can call `self.c.OnUIThread(myOtherFunc)`.
|
||||||
|
|
||||||
|
## Legacy code structure
|
||||||
|
|
||||||
|
Before we had controllers and contexts, all the code lived directly in the gui package under a gui God Struct. This was fairly bloated and so we split things out to have a better separation of concerns. Nonetheless, it's a big effort to migrate all the code so we still have some logic in the gui struct that ought to live somewhere else. Likewise, we have some keybindings defined in `pkg/gui/keybindings.go` that ought to live on a controller (all keybindings used to be defined in that one file).
|
||||||
|
|
||||||
|
The new structure has its own problems: we don't have a clear guide on whether code should live in a controller or helper. The current approach is to put code in a controller until it's needed by another controller, and to then extract it out into a helper. We may be better off just putting code in helpers to start with and leaving controllers super-thin, with the responsibility of just pairing keys with corresponding helper functions. But it's not clear to me if that would be better than the current approach.
|
||||||
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# Demo Recordings
|
||||||
|
|
||||||
|
We want our demo recordings to be consistent and easy to update if we make changes to Lazygit's UI. Luckily for us, we have an existing recording system for the sake of our integration tests, so we can piggyback on that.
|
||||||
|
|
||||||
|
You'll want to familiarise yourself with how integration tests are written: see [here](../../pkg/integration/README.md).
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Ideally we'd run this whole thing through docker but we haven't got that working. So you will need:
|
||||||
|
```
|
||||||
|
# for recording
|
||||||
|
npm i -g terminalizer
|
||||||
|
# for gif compression
|
||||||
|
npm i -g gifsicle
|
||||||
|
# for mp4 conversion
|
||||||
|
brew install ffmpeg
|
||||||
|
|
||||||
|
# font with icons
|
||||||
|
wget https://github.com/ryanoasis/nerd-fonts/releases/download/v3.0.2/DejaVuSansMono.tar.xz && \
|
||||||
|
tar -xf DejaVuSansMono.tar.xz -C /usr/local/share/fonts && \
|
||||||
|
rm DejaVuSansMono.tar.xz
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating a demo
|
||||||
|
|
||||||
|
Demos are found in `pkg/integration/tests/demo/`. They are like regular integration tests but have `IsDemo: true` which has a few effects:
|
||||||
|
* The bottom row of the UI is quieter so that we can render captions
|
||||||
|
* Fetch/Push/Pull have artificial latency to mimic a network request
|
||||||
|
* The loader at the bottom-right does not appear
|
||||||
|
|
||||||
|
In demos, we don't need to be as strict in our assertions as we are in tests. But it's still good to have some basic assertions so that if we automate the process of updating demos we'll know if one of them has broken.
|
||||||
|
|
||||||
|
You can use the same flow as we use with integration tests when you're writing a demo:
|
||||||
|
* Setup the repo
|
||||||
|
* Run the demo in sandbox mode to get a feel of what needs to happen
|
||||||
|
* Come back and write the code to make it happen
|
||||||
|
|
||||||
|
### Adding captions
|
||||||
|
|
||||||
|
It's good to add captions explaining what task if being performed. Use the existing demos as a guide.
|
||||||
|
|
||||||
|
### Setting up the assets worktree
|
||||||
|
|
||||||
|
We store assets (which includes demo recordings) in the `assets` branch, which is a branch that shares no history with the main branch and exists purely for storing assets. Storing them separately means we don't clog up the code branches with large binaries.
|
||||||
|
|
||||||
|
The scripts and demo definitions live in the code branches but the output lives in the assets branch so to be able to create a video from a demo you'll need to create a linked worktree for the assets branch which you can do with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git worktree add .worktrees/assets assets
|
||||||
|
```
|
||||||
|
|
||||||
|
Outputs will be stored in `.worktrees/assets/demos/`. We'll store three separate things:
|
||||||
|
* the yaml of the recording
|
||||||
|
* the original gif
|
||||||
|
* either the compressed gif or the mp4 depending on the output you chose (see below)
|
||||||
|
|
||||||
|
### Recording the demo
|
||||||
|
|
||||||
|
Once you're happy with your demo you can record it using:
|
||||||
|
```sh
|
||||||
|
scripts/record_demo.sh [gif|mp4] <path>
|
||||||
|
# e.g.
|
||||||
|
scripts/record_demo.sh gif pkg/integration/tests/demo/interactive_rebase.go
|
||||||
|
```
|
||||||
|
|
||||||
|
~~The gif format is for use in the first video of the readme (it has a larger size but has auto-play and looping)~~
|
||||||
|
~~The mp4 format is for everything else (no looping, requires clicking, but smaller size).~~
|
||||||
|
|
||||||
|
Turns out that you can't store mp4s in a repo and link them from a README so we're gonna just use gifs across the board for now.
|
||||||
|
|
||||||
|
### Including demos in README/docs
|
||||||
|
|
||||||
|
If you've followed the above steps you'll end up with your output in your assets worktree.
|
||||||
|
|
||||||
|
Within that worktree, stage all three output files and raise a PR against the assets branch.
|
||||||
|
|
||||||
|
Then back in the code branch, in the doc, you can embed the recording like so:
|
||||||
|
```md
|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
This means we can update assets without needing to update the docs that embed them.
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
# Dev Documentation Overview
|
# Dev Documentation Overview
|
||||||
|
|
||||||
* [Busy/Idle tracking](./Busy.md).
|
* [Codebase Guide](./Codebase_Guide.md)
|
||||||
|
* [Busy/Idle Tracking](./Busy.md)
|
||||||
* [Integration Tests](../../pkg/integration/README.md)
|
* [Integration Tests](../../pkg/integration/README.md)
|
||||||
|
* [Demo Recordings](./Demo_Recordings.md)
|
||||||
|
|||||||
+296
-266
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit Keybindings
|
# Lazygit Keybindings
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
|
|
||||||
## Global keybindings
|
## Global keybindings
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: Switch to a recent repo
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: Scroll up main panel (fn+up/shift+k)
|
| `` <c-r> `` | Switch to a recent repo | |
|
||||||
<kbd><pgdown></kbd>: Scroll down main panel (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | Scroll up main window | |
|
||||||
<kbd>@</kbd>: Open command log menu
|
| `` <pgdown> (fn+down/shift+j) `` | Scroll down main window | |
|
||||||
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
|
| `` @ `` | View command log options | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
|
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: Execute custom command
|
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: View custom patch options
|
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: View merge/rebase options
|
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: Refresh
|
| `` : `` | Execute custom command | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: Next screen mode (normal/half/fullscreen)
|
| `` <c-p> `` | View custom patch options | |
|
||||||
<kbd>_</kbd>: Prev screen mode
|
| `` m `` | View merge/rebase options | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: Open menu
|
| `` R `` | Refresh | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: View filter-by-path options
|
| `` + `` | Next screen mode (normal/half/fullscreen) | |
|
||||||
<kbd>W</kbd>: Open diff menu
|
| `` _ `` | Prev screen mode | |
|
||||||
<kbd><c-e></kbd>: Open diff menu
|
| `` ? `` | Open keybindings menu | |
|
||||||
<kbd><c-w></kbd>: Toggle whether or not whitespace changes are shown in the diff view
|
| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: Undo
|
| `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: Redo
|
| `` <c-e> `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: Push
|
| `` q `` | Quit | |
|
||||||
<kbd>p</kbd>: Pull
|
| `` <esc> `` | Cancel | |
|
||||||
</pre>
|
| `` <c-w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | Undo | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
| `` <c-z> `` | Redo | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
|
||||||
## List panel navigation
|
## List panel navigation
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: Previous page
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: Next page
|
| `` , `` | Previous page | |
|
||||||
<kbd><</kbd>: Scroll to top
|
| `` . `` | Next page | |
|
||||||
<kbd>></kbd>: Scroll to bottom
|
| `` < `` | Scroll to top | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` > `` | Scroll to bottom | |
|
||||||
<kbd>H</kbd>: Scroll left
|
| `` v `` | Toggle range select | |
|
||||||
<kbd>L</kbd>: Scroll right
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: Next tab
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: Previous tab
|
| `` / `` | Search the current view by text | |
|
||||||
</pre>
|
| `` H `` | Scroll left | |
|
||||||
|
| `` L `` | Scroll right | |
|
||||||
|
| `` ] `` | Next tab | |
|
||||||
|
| `` [ `` | Previous tab | |
|
||||||
|
|
||||||
## Commit files
|
## Commit files
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy the committed file name to the clipboard
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: Checkout file
|
| `` <c-o> `` | Copy path to clipboard | |
|
||||||
<kbd>d</kbd>: Discard this commit's changes to this file
|
| `` c `` | Checkout | Checkout file. This replaces the file in your working tree with the version from the selected commit. |
|
||||||
<kbd>o</kbd>: Open file
|
| `` d `` | Remove | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
|
||||||
<kbd>e</kbd>: Edit file
|
| `` o `` | Open file | Open file in default application. |
|
||||||
<kbd><space></kbd>: Toggle file included in patch
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Toggle all files included in patch
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
|
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: Toggle file tree view
|
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` <enter> `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Commit summary
|
## Commit summary
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Confirm
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Close
|
| `` <enter> `` | Confirm | |
|
||||||
</pre>
|
| `` <esc> `` | Close | |
|
||||||
|
|
||||||
## Commits
|
## Commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy commit SHA to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||||
<kbd>b</kbd>: View bisect options
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd>s</kbd>: Squash down
|
| `` b `` | View bisect options | |
|
||||||
<kbd>f</kbd>: Fixup commit
|
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: Reword commit
|
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: Reword commit with editor
|
| `` r `` | Reword | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: Delete commit
|
| `` R `` | Reword with editor | |
|
||||||
<kbd>e</kbd>: Edit commit
|
| `` d `` | Drop | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: Pick commit (when mid-rebase)
|
| `` e `` | Edit (start interactive rebase) | Edit the selected commit. Use this to start an interactive rebase from the selected commit. When already mid-rebase, this will mark the selected commit for editing, which means that upon continuing the rebase, the rebase will pause at the selected commit to allow you to make changes. |
|
||||||
<kbd>F</kbd>: Create fixup commit for this commit
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: Move commit down one
|
| `` p `` | Pick | Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase. |
|
||||||
<kbd><c-k></kbd>: Move commit up one
|
| `` F `` | Create fixup commit | Create 'fixup!' commit for the selected commit. Later on, you can press `S` on this same commit to apply all above fixup commits. |
|
||||||
<kbd>v</kbd>: Paste commits (cherry-pick)
|
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash). |
|
||||||
<kbd>A</kbd>: Amend commit with staged changes
|
| `` <c-j> `` | Move commit down one | |
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
| `` <c-k> `` | Move commit up one | |
|
||||||
<kbd>t</kbd>: Revert commit
|
| `` V `` | Paste (cherry-pick) | |
|
||||||
<kbd>T</kbd>: Tag commit
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: Open log menu
|
| `` A `` | Amend | Amend commit with staged changes. If the selected commit is the HEAD commit, this will perform `git commit --amend`. Otherwise the commit will be amended via a rebase. |
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
| `` <c-l> `` | View log options | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: Copy commit (cherry-pick)
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: Copy commit range (cherry-pick)
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` n `` | Create new branch off of commit | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | View files | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Confirmation panel
|
## Confirmation panel
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Confirm
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Close/Cancel
|
| `` <enter> `` | Confirm | |
|
||||||
</pre>
|
| `` <esc> `` | Close/Cancel | |
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy the file name to the clipboard
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: View 'discard changes' options
|
| `` <c-o> `` | Copy path to clipboard | |
|
||||||
<kbd><space></kbd>: Toggle staged
|
| `` <space> `` | Stage | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: Filter files by status
|
| `` <c-b> `` | Filter files by status | |
|
||||||
<kbd>c</kbd>: Commit changes
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: Commit changes without pre-commit hook
|
| `` c `` | Commit | Commit staged changes. |
|
||||||
<kbd>A</kbd>: Amend last commit
|
| `` w `` | Commit changes without pre-commit hook | |
|
||||||
<kbd>C</kbd>: Commit changes using git editor
|
| `` A `` | Amend last commit | |
|
||||||
<kbd>e</kbd>: Edit file
|
| `` C `` | Commit changes using git editor | |
|
||||||
<kbd>o</kbd>: Open file
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: Ignore or exclude file
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: Refresh files
|
| `` o `` | Open file | Open file in default application. |
|
||||||
<kbd>s</kbd>: Stash all changes
|
| `` i `` | Ignore or exclude file | |
|
||||||
<kbd>S</kbd>: View stash options
|
| `` r `` | Refresh files | |
|
||||||
<kbd>a</kbd>: Stage/unstage all
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: Stage individual hunks/lines for file, or collapse/expand for directory
|
| `` S `` | View stash options | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: View upstream reset options
|
| `` a `` | Stage all | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: View reset options
|
| `` <enter> `` | Stage lines / Collapse directory | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: Toggle file tree view
|
| `` d `` | Discard | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: Open external merge tool (git mergetool)
|
| `` g `` | View upstream reset options | |
|
||||||
<kbd>f</kbd>: Fetch
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | Open external merge tool | Run `git mergetool`. |
|
||||||
|
| `` f `` | Fetch | Fetch changes from remote. |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Local branches
|
## Local branches
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy branch name to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: Show git-flow options
|
| `` <c-o> `` | Copy branch name to clipboard | |
|
||||||
<kbd><space></kbd>: Checkout
|
| `` i `` | Show git-flow options | |
|
||||||
<kbd>n</kbd>: New branch
|
| `` <space> `` | Checkout | Checkout selected item. |
|
||||||
<kbd>o</kbd>: Create pull request
|
| `` n `` | New branch | |
|
||||||
<kbd>O</kbd>: Create pull request options
|
| `` o `` | Create pull request | |
|
||||||
<kbd><c-y></kbd>: Copy pull request URL to clipboard
|
| `` O `` | View create pull request options | |
|
||||||
<kbd>c</kbd>: Checkout by name
|
| `` <c-y> `` | Copy pull request URL to clipboard | |
|
||||||
<kbd>F</kbd>: Force checkout
|
| `` c `` | Checkout by name | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: Delete branch
|
| `` F `` | Force checkout | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: Rebase checked-out branch onto this branch
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: Merge into currently checked out branch
|
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: Fast-forward this branch from its upstream
|
| `` M `` | Merge | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: Create tag
|
| `` f `` | Fast-forward | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` T `` | New tag | |
|
||||||
<kbd>R</kbd>: Rename branch
|
| `` s `` | Sort order | |
|
||||||
<kbd>u</kbd>: Set/Unset upstream
|
| `` g `` | Reset | |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` R `` | Rename branch | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | View commits | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Main panel (merging)
|
## Main panel (merging)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: Edit file
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: Open file
|
| `` <space> `` | Pick hunk | |
|
||||||
<kbd><left></kbd>: Select previous conflict
|
| `` b `` | Pick all hunks | |
|
||||||
<kbd><right></kbd>: Select next conflict
|
| `` <up> `` | Previous hunk | |
|
||||||
<kbd><up></kbd>: Select previous hunk
|
| `` <down> `` | Next hunk | |
|
||||||
<kbd><down></kbd>: Select next hunk
|
| `` <left> `` | Previous conflict | |
|
||||||
<kbd>z</kbd>: Undo
|
| `` <right> `` | Next conflict | |
|
||||||
<kbd>M</kbd>: Open external merge tool (git mergetool)
|
| `` z `` | Undo | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: Pick hunk
|
| `` e `` | Edit file | Open file in external editor. |
|
||||||
<kbd>b</kbd>: Pick all hunks
|
| `` o `` | Open file | Open file in default application. |
|
||||||
<kbd><esc></kbd>: Return to files panel
|
| `` M `` | Open external merge tool | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | Return to files panel | |
|
||||||
|
|
||||||
## Main panel (normal)
|
## Main panel (normal)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: Scroll down (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: Scroll up (fn+down)
|
| `` mouse wheel down (fn+up) `` | Scroll down | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | Scroll up | |
|
||||||
|
|
||||||
## Main panel (patch building)
|
## Main panel (patch building)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Select previous hunk
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Select next hunk
|
| `` <left> `` | Go to previous hunk | |
|
||||||
<kbd>v</kbd>: Toggle drag select
|
| `` <right> `` | Go to next hunk | |
|
||||||
<kbd>V</kbd>: Toggle drag select
|
| `` v `` | Toggle range select | |
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
| `` a `` | Select hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
| `` <c-o> `` | Copy selected text to clipboard | |
|
||||||
<kbd>o</kbd>: Open file
|
| `` o `` | Open file | Open file in default application. |
|
||||||
<kbd>e</kbd>: Edit file
|
| `` e `` | Edit file | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Add/Remove line(s) to patch
|
| `` <space> `` | Toggle lines in patch | |
|
||||||
<kbd><esc></kbd>: Exit custom patch builder
|
| `` <esc> `` | Exit custom patch builder | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` / `` | Search the current view by text | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Main panel (staging)
|
## Main panel (staging)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Select previous hunk
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Select next hunk
|
| `` <left> `` | Go to previous hunk | |
|
||||||
<kbd>v</kbd>: Toggle drag select
|
| `` <right> `` | Go to next hunk | |
|
||||||
<kbd>V</kbd>: Toggle drag select
|
| `` v `` | Toggle range select | |
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
| `` a `` | Select hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
| `` <c-o> `` | Copy selected text to clipboard | |
|
||||||
<kbd>o</kbd>: Open file
|
| `` <space> `` | Stage | Toggle selection staged / unstaged. |
|
||||||
<kbd>e</kbd>: Edit file
|
| `` d `` | Discard | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: Return to files panel
|
| `` o `` | Open file | Open file in default application. |
|
||||||
<kbd><tab></kbd>: Switch to other panel (staged/unstaged changes)
|
| `` e `` | Edit file | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Toggle line staged / unstaged
|
| `` <esc> `` | Return to files panel | |
|
||||||
<kbd>d</kbd>: Discard change (git reset)
|
| `` <tab> `` | Switch view | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Edit hunk
|
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: Commit changes
|
| `` c `` | Commit | Commit staged changes. |
|
||||||
<kbd>w</kbd>: Commit changes without pre-commit hook
|
| `` w `` | Commit changes without pre-commit hook | |
|
||||||
<kbd>C</kbd>: Commit changes using git editor
|
| `` C `` | Commit changes using git editor | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` / `` | Search the current view by text | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Menu
|
## Menu
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Execute
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Close
|
| `` <enter> `` | Execute | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | Close | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Reflog
|
## Reflog
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy commit SHA to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` n `` | Create new branch off of commit | |
|
||||||
<kbd>c</kbd>: Copy commit (cherry-pick)
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Copy commit range (cherry-pick)
|
| `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View commits | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Remote branches
|
## Remote branches
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy branch name to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout
|
| `` <c-o> `` | Copy branch name to clipboard | |
|
||||||
<kbd>n</kbd>: New branch
|
| `` <space> `` | Checkout | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: Merge into currently checked out branch
|
| `` n `` | New branch | |
|
||||||
<kbd>r</kbd>: Rebase checked-out branch onto this branch
|
| `` M `` | Merge | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: Delete branch
|
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: Set as upstream of checked-out branch
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` s `` | Sort order | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | View commits | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Remotes
|
## Remotes
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: Fetch remote
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: Add new remote
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: Remove remote
|
| `` n `` | New remote | |
|
||||||
<kbd>e</kbd>: Edit remote
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | Edit the selected remote's name or URL. |
|
||||||
</pre>
|
| `` f `` | Fetch | Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Stash
|
## Stash
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Apply
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: Pop
|
| `` <space> `` | Apply | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: Drop
|
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: New branch
|
| `` d `` | Drop | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Rename stash
|
| `` n `` | New branch | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` r `` | Rename stash | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View files | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: Open config file
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: Edit config file
|
| `` o `` | Open config file | Open file in default application. |
|
||||||
<kbd>u</kbd>: Check for update
|
| `` e `` | Edit config file | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: Switch to a recent repo
|
| `` u `` | Check for update | |
|
||||||
<kbd>a</kbd>: Show all branch logs
|
| `` <enter> `` | Switch to a recent repo | |
|
||||||
</pre>
|
| `` a `` | Show all branch logs | |
|
||||||
|
|
||||||
## Sub-commits
|
## Sub-commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy commit SHA to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | Checkout | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` n `` | Create new branch off of commit | |
|
||||||
<kbd>c</kbd>: Copy commit (cherry-pick)
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Copy commit range (cherry-pick)
|
| `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` <enter> `` | View files | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Submodules
|
## Submodules
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy submodule name to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: Enter submodule
|
| `` <c-o> `` | Copy submodule name to clipboard | |
|
||||||
<kbd>d</kbd>: Remove submodule
|
| `` <enter> `` | Enter | Enter submodule. After entering the submodule, you can press `<esc>` to escape back to the parent repo. |
|
||||||
<kbd>u</kbd>: Update submodule
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: Add new submodule
|
| `` u `` | Update | Update selected submodule. |
|
||||||
<kbd>e</kbd>: Update submodule URL
|
| `` n `` | New submodule | |
|
||||||
<kbd>i</kbd>: Initialize submodule
|
| `` e `` | Update submodule URL | |
|
||||||
<kbd>b</kbd>: View bulk submodule options
|
| `` i `` | Initialize | Initialize the selected submodule to prepare for fetching. You probably want to follow this up by invoking the 'update' action to fetch the submodule. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | View bulk submodule options | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Tags
|
## Tags
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Checkout
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Delete tag
|
| `` <space> `` | Checkout | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: Push tag
|
| `` n `` | New tag | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Create tag
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View commits | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|||||||
+296
-266
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit キーバインド
|
# Lazygit キーバインド
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
|
|
||||||
## グローバルキーバインド
|
## グローバルキーバインド
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: 最近使用したリポジトリに切り替え
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: メインパネルを上にスクロール (fn+up/shift+k)
|
| `` <c-r> `` | 最近使用したリポジトリに切り替え | |
|
||||||
<kbd><pgdown></kbd>: メインパネルを下にスクロール (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | メインパネルを上にスクロール | |
|
||||||
<kbd>@</kbd>: コマンドログメニューを開く
|
| `` <pgdown> (fn+down/shift+j) `` | メインパネルを下にスクロール | |
|
||||||
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
|
| `` @ `` | コマンドログメニューを開く | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
|
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: カスタムコマンドを実行
|
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: View custom patch options
|
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: View merge/rebase options
|
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: リフレッシュ
|
| `` : `` | カスタムコマンドを実行 | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: 次のスクリーンモード (normal/half/fullscreen)
|
| `` <c-p> `` | View custom patch options | |
|
||||||
<kbd>_</kbd>: 前のスクリーンモード
|
| `` m `` | View merge/rebase options | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: メニューを開く
|
| `` R `` | リフレッシュ | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: View filter-by-path options
|
| `` + `` | 次のスクリーンモード (normal/half/fullscreen) | |
|
||||||
<kbd>W</kbd>: 差分メニューを開く
|
| `` _ `` | 前のスクリーンモード | |
|
||||||
<kbd><c-e></kbd>: 差分メニューを開く
|
| `` ? `` | メニューを開く | |
|
||||||
<kbd><c-w></kbd>: 空白文字の差分の表示有無を切り替え
|
| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: アンドゥ (via reflog) (experimental)
|
| `` W `` | 差分メニューを開く | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: リドゥ (via reflog) (experimental)
|
| `` <c-e> `` | 差分メニューを開く | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: Push
|
| `` q `` | 終了 | |
|
||||||
<kbd>p</kbd>: Pull
|
| `` <esc> `` | キャンセル | |
|
||||||
</pre>
|
| `` <c-w> `` | 空白文字の差分の表示有無を切り替え | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | アンドゥ (via reflog) (experimental) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
| `` <c-z> `` | リドゥ (via reflog) (experimental) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
|
||||||
## 一覧パネルの操作
|
## 一覧パネルの操作
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: 前のページ
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: 次のページ
|
| `` , `` | 前のページ | |
|
||||||
<kbd><</kbd>: 最上部までスクロール
|
| `` . `` | 次のページ | |
|
||||||
<kbd>></kbd>: 最下部までスクロール
|
| `` < `` | 最上部までスクロール | |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` > `` | 最下部までスクロール | |
|
||||||
<kbd>H</kbd>: 左スクロール
|
| `` v `` | 範囲選択を切り替え | |
|
||||||
<kbd>L</kbd>: 右スクロール
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: 次のタブ
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: 前のタブ
|
| `` / `` | 検索を開始 | |
|
||||||
</pre>
|
| `` H `` | 左スクロール | |
|
||||||
|
| `` L `` | 右スクロール | |
|
||||||
|
| `` ] `` | 次のタブ | |
|
||||||
|
| `` [ `` | 前のタブ | |
|
||||||
|
|
||||||
## Stash
|
## Stash
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 適用
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: Pop
|
| `` <space> `` | 適用 | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: Drop
|
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: 新しいブランチを作成
|
| `` d `` | Drop | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Stashを変更
|
| `` n `` | 新しいブランチを作成 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` r `` | Stashを変更 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View files | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Sub-commits
|
## Sub-commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: コミットのSHAをクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: コミットをチェックアウト
|
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
|
||||||
<kbd>y</kbd>: コミットの情報をコピー
|
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: ブラウザでコミットを開く
|
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: コミットにブランチを作成
|
| `` o `` | ブラウザでコミットを開く | |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` n `` | コミットにブランチを作成 | |
|
||||||
<kbd>c</kbd>: コミットをコピー (cherry-pick)
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
|
| `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` <enter> `` | View files | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 検索を開始 | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## コミット
|
## コミット
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: コミットのSHAをクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
|
||||||
<kbd>b</kbd>: View bisect options
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd>s</kbd>: Squash down
|
| `` b `` | View bisect options | |
|
||||||
<kbd>f</kbd>: Fixup commit
|
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: コミットメッセージを変更
|
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: エディタでコミットメッセージを編集
|
| `` r `` | コミットメッセージを変更 | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: コミットを削除
|
| `` R `` | エディタでコミットメッセージを編集 | |
|
||||||
<kbd>e</kbd>: コミットを編集
|
| `` d `` | コミットを削除 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: Pick commit (when mid-rebase)
|
| `` e `` | Edit (start interactive rebase) | コミットを編集 |
|
||||||
<kbd>F</kbd>: このコミットに対するfixupコミットを作成
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: コミットを1つ下に移動
|
| `` p `` | Pick | Mark the selected commit to be picked (when mid-rebase). This means that the commit will be retained upon continuing the rebase. |
|
||||||
<kbd><c-k></kbd>: コミットを1つ上に移動
|
| `` F `` | Create fixup commit | このコミットに対するfixupコミットを作成 |
|
||||||
<kbd>v</kbd>: コミットを貼り付け (cherry-pick)
|
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits, either above the selected commit, or all in current branch (autosquash). |
|
||||||
<kbd>A</kbd>: ステージされた変更でamendコミット
|
| `` <c-j> `` | コミットを1つ下に移動 | |
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
| `` <c-k> `` | コミットを1つ上に移動 | |
|
||||||
<kbd>t</kbd>: コミットをrevert
|
| `` V `` | コミットを貼り付け (cherry-pick) | |
|
||||||
<kbd>T</kbd>: タグを作成
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: ログメニューを開く
|
| `` A `` | Amend | ステージされた変更でamendコミット |
|
||||||
<kbd><space></kbd>: コミットをチェックアウト
|
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: コミットの情報をコピー
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: ブラウザでコミットを開く
|
| `` T `` | タグを作成 | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: コミットにブランチを作成
|
| `` <c-l> `` | ログメニューを開く | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: コミットをコピー (cherry-pick)
|
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
|
| `` o `` | ブラウザでコミットを開く | |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` n `` | コミットにブランチを作成 | |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | View files | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 検索を開始 | |
|
||||||
|
|
||||||
## コミットファイル
|
## コミットファイル
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: コミットされたファイル名をクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: Checkout file
|
| `` <c-o> `` | ファイル名をクリップボードにコピー | |
|
||||||
<kbd>d</kbd>: Discard this commit's changes to this file
|
| `` c `` | チェックアウト | Checkout file. This replaces the file in your working tree with the version from the selected commit. |
|
||||||
<kbd>o</kbd>: ファイルを開く
|
| `` d `` | Remove | Discard this commit's changes to this file. This runs an interactive rebase in the background, so you may get a merge conflict if a later commit also changes this file. |
|
||||||
<kbd>e</kbd>: ファイルを編集
|
| `` o `` | ファイルを開く | Open file in default application. |
|
||||||
<kbd><space></kbd>: Toggle file included in patch
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Toggle all files included in patch
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
|
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: ファイルツリーの表示を切り替え
|
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` <enter> `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | ファイルツリーの表示を切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | 検索を開始 | |
|
||||||
|
|
||||||
## コミットメッセージ
|
## コミットメッセージ
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 確認
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 閉じる
|
| `` <enter> `` | 確認 | |
|
||||||
</pre>
|
| `` <esc> `` | 閉じる | |
|
||||||
|
|
||||||
## サブモジュール
|
## サブモジュール
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: サブモジュール名をクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: サブモジュールを開く
|
| `` <c-o> `` | サブモジュール名をクリップボードにコピー | |
|
||||||
<kbd>d</kbd>: サブモジュールを削除
|
| `` <enter> `` | Enter | サブモジュールを開く |
|
||||||
<kbd>u</kbd>: サブモジュールを更新
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: サブモジュールを新規追加
|
| `` u `` | Update | サブモジュールを更新 |
|
||||||
<kbd>e</kbd>: サブモジュールのURLを更新
|
| `` n `` | サブモジュールを新規追加 | |
|
||||||
<kbd>i</kbd>: サブモジュールを初期化
|
| `` e `` | サブモジュールのURLを更新 | |
|
||||||
<kbd>b</kbd>: View bulk submodule options
|
| `` i `` | Initialize | サブモジュールを初期化 |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | View bulk submodule options | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## ステータス
|
## ステータス
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: 設定ファイルを開く
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: 設定ファイルを編集
|
| `` o `` | 設定ファイルを開く | Open file in default application. |
|
||||||
<kbd>u</kbd>: 更新を確認
|
| `` e `` | 設定ファイルを編集 | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: 最近使用したリポジトリに切り替え
|
| `` u `` | 更新を確認 | |
|
||||||
<kbd>a</kbd>: すべてのブランチログを表示
|
| `` <enter> `` | 最近使用したリポジトリに切り替え | |
|
||||||
</pre>
|
| `` a `` | すべてのブランチログを表示 | |
|
||||||
|
|
||||||
## タグ
|
## タグ
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: チェックアウト
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: タグを削除
|
| `` <space> `` | チェックアウト | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: タグをpush
|
| `` n `` | タグを作成 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: タグを作成
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` P `` | タグをpush | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: コミットを閲覧
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | コミットを閲覧 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## ファイル
|
## ファイル
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: ファイル名をクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: View 'discard changes' options
|
| `` <c-o> `` | ファイル名をクリップボードにコピー | |
|
||||||
<kbd><space></kbd>: ステージ/アンステージ
|
| `` <space> `` | ステージ/アンステージ | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: ファイルをフィルタ (ステージ/アンステージ)
|
| `` <c-b> `` | ファイルをフィルタ (ステージ/アンステージ) | |
|
||||||
<kbd>c</kbd>: 変更をコミット
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: pre-commitフックを実行せずに変更をコミット
|
| `` c `` | 変更をコミット | Commit staged changes. |
|
||||||
<kbd>A</kbd>: 最新のコミットにamend
|
| `` w `` | pre-commitフックを実行せずに変更をコミット | |
|
||||||
<kbd>C</kbd>: gitエディタを使用して変更をコミット
|
| `` A `` | 最新のコミットにamend | |
|
||||||
<kbd>e</kbd>: ファイルを編集
|
| `` C `` | gitエディタを使用して変更をコミット | |
|
||||||
<kbd>o</kbd>: ファイルを開く
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: ファイルをignore
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: ファイルをリフレッシュ
|
| `` o `` | ファイルを開く | Open file in default application. |
|
||||||
<kbd>s</kbd>: 変更をstash
|
| `` i `` | ファイルをignore | |
|
||||||
<kbd>S</kbd>: View stash options
|
| `` r `` | ファイルをリフレッシュ | |
|
||||||
<kbd>a</kbd>: すべての変更をステージ/アンステージ
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: Stage individual hunks/lines for file, or collapse/expand for directory
|
| `` S `` | View stash options | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: View upstream reset options
|
| `` a `` | すべての変更をステージ/アンステージ | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: View reset options
|
| `` <enter> `` | Stage lines / Collapse directory | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: ファイルツリーの表示を切り替え
|
| `` d `` | Discard | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: Git mergetoolを開く
|
| `` g `` | View upstream reset options | |
|
||||||
<kbd>f</kbd>: Fetch
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` ` `` | ファイルツリーの表示を切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | Git mergetoolを開く | Run `git mergetool`. |
|
||||||
|
| `` f `` | Fetch | Fetch changes from remote. |
|
||||||
|
| `` / `` | 検索を開始 | |
|
||||||
|
|
||||||
## ブランチ
|
## ブランチ
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: ブランチ名をクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: Show git-flow options
|
| `` <c-o> `` | ブランチ名をクリップボードにコピー | |
|
||||||
<kbd><space></kbd>: チェックアウト
|
| `` i `` | Show git-flow options | |
|
||||||
<kbd>n</kbd>: 新しいブランチを作成
|
| `` <space> `` | チェックアウト | Checkout selected item. |
|
||||||
<kbd>o</kbd>: Pull Requestを作成
|
| `` n `` | 新しいブランチを作成 | |
|
||||||
<kbd>O</kbd>: Create pull request options
|
| `` o `` | Pull Requestを作成 | |
|
||||||
<kbd><c-y></kbd>: Pull RequestのURLをクリップボードにコピー
|
| `` O `` | View create pull request options | |
|
||||||
<kbd>c</kbd>: Checkout by name
|
| `` <c-y> `` | Pull RequestのURLをクリップボードにコピー | |
|
||||||
<kbd>F</kbd>: Force checkout
|
| `` c `` | Checkout by name | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: ブランチを削除
|
| `` F `` | Force checkout | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: Rebase checked-out branch onto this branch
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: 現在のブランチにマージ
|
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: Fast-forward this branch from its upstream
|
| `` M `` | 現在のブランチにマージ | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: タグを作成
|
| `` f `` | Fast-forward | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` T `` | タグを作成 | |
|
||||||
<kbd>R</kbd>: ブランチ名を変更
|
| `` s `` | 並び替え | |
|
||||||
<kbd>u</kbd>: Set/Unset upstream
|
| `` g `` | Reset | |
|
||||||
<kbd><enter></kbd>: コミットを閲覧
|
| `` R `` | ブランチ名を変更 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | コミットを閲覧 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## メインパネル (Merging)
|
## メインパネル (Merging)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: ファイルを編集
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: ファイルを開く
|
| `` <space> `` | Pick hunk | |
|
||||||
<kbd><left></kbd>: 前のコンフリクトを選択
|
| `` b `` | Pick all hunks | |
|
||||||
<kbd><right></kbd>: 次のコンフリクトを選択
|
| `` <up> `` | 前のhunkを選択 | |
|
||||||
<kbd><up></kbd>: 前のhunkを選択
|
| `` <down> `` | 次のhunkを選択 | |
|
||||||
<kbd><down></kbd>: 次のhunkを選択
|
| `` <left> `` | 前のコンフリクトを選択 | |
|
||||||
<kbd>z</kbd>: アンドゥ
|
| `` <right> `` | 次のコンフリクトを選択 | |
|
||||||
<kbd>M</kbd>: Git mergetoolを開く
|
| `` z `` | アンドゥ | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: Pick hunk
|
| `` e `` | ファイルを編集 | Open file in external editor. |
|
||||||
<kbd>b</kbd>: Pick all hunks
|
| `` o `` | ファイルを開く | Open file in default application. |
|
||||||
<kbd><esc></kbd>: ファイル一覧に戻る
|
| `` M `` | Git mergetoolを開く | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | ファイル一覧に戻る | |
|
||||||
|
|
||||||
## メインパネル (Normal)
|
## メインパネル (Normal)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: 下にスクロール (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: 上にスクロール (fn+down)
|
| `` mouse wheel down (fn+up) `` | 下にスクロール | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | 上にスクロール | |
|
||||||
|
|
||||||
## メインパネル (Patch Building)
|
## メインパネル (Patch Building)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 前のhunkを選択
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 次のhunkを選択
|
| `` <left> `` | 前のhunkを選択 | |
|
||||||
<kbd>v</kbd>: 範囲選択を切り替え
|
| `` <right> `` | 次のhunkを選択 | |
|
||||||
<kbd>V</kbd>: 範囲選択を切り替え
|
| `` v `` | 範囲選択を切り替え | |
|
||||||
<kbd>a</kbd>: Hunk選択を切り替え
|
| `` a `` | Hunk選択を切り替え | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 選択されたテキストをクリップボードにコピー
|
| `` <c-o> `` | 選択されたテキストをクリップボードにコピー | |
|
||||||
<kbd>o</kbd>: ファイルを開く
|
| `` o `` | ファイルを開く | Open file in default application. |
|
||||||
<kbd>e</kbd>: ファイルを編集
|
| `` e `` | ファイルを編集 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 行をパッチに追加/削除
|
| `` <space> `` | 行をパッチに追加/削除 | |
|
||||||
<kbd><esc></kbd>: Exit custom patch builder
|
| `` <esc> `` | Exit custom patch builder | |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` / `` | 検索を開始 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## メインパネル (Staging)
|
## メインパネル (Staging)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 前のhunkを選択
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 次のhunkを選択
|
| `` <left> `` | 前のhunkを選択 | |
|
||||||
<kbd>v</kbd>: 範囲選択を切り替え
|
| `` <right> `` | 次のhunkを選択 | |
|
||||||
<kbd>V</kbd>: 範囲選択を切り替え
|
| `` v `` | 範囲選択を切り替え | |
|
||||||
<kbd>a</kbd>: Hunk選択を切り替え
|
| `` a `` | Hunk選択を切り替え | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 選択されたテキストをクリップボードにコピー
|
| `` <c-o> `` | 選択されたテキストをクリップボードにコピー | |
|
||||||
<kbd>o</kbd>: ファイルを開く
|
| `` <space> `` | ステージ/アンステージ | 選択行をステージ/アンステージ |
|
||||||
<kbd>e</kbd>: ファイルを編集
|
| `` d `` | 変更を削除 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: ファイル一覧に戻る
|
| `` o `` | ファイルを開く | Open file in default application. |
|
||||||
<kbd><tab></kbd>: パネルを切り替え
|
| `` e `` | ファイルを編集 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 選択行をステージ/アンステージ
|
| `` <esc> `` | ファイル一覧に戻る | |
|
||||||
<kbd>d</kbd>: 変更を削除 (git reset)
|
| `` <tab> `` | パネルを切り替え | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Edit hunk
|
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: 変更をコミット
|
| `` c `` | 変更をコミット | Commit staged changes. |
|
||||||
<kbd>w</kbd>: pre-commitフックを実行せずに変更をコミット
|
| `` w `` | pre-commitフックを実行せずに変更をコミット | |
|
||||||
<kbd>C</kbd>: gitエディタを使用して変更をコミット
|
| `` C `` | gitエディタを使用して変更をコミット | |
|
||||||
<kbd>/</kbd>: 検索を開始
|
| `` / `` | 検索を開始 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## メニュー
|
## メニュー
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 実行
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 閉じる
|
| `` <enter> `` | 実行 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | 閉じる | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## リモート
|
## リモート
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: リモートをfetch
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: リモートを新規追加
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: リモートを削除
|
| `` n `` | リモートを新規追加 | |
|
||||||
<kbd>e</kbd>: リモートを編集
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | リモートを編集 |
|
||||||
</pre>
|
| `` f `` | Fetch | リモートをfetch |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## リモートブランチ
|
## リモートブランチ
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: ブランチ名をクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: チェックアウト
|
| `` <c-o> `` | ブランチ名をクリップボードにコピー | |
|
||||||
<kbd>n</kbd>: 新しいブランチを作成
|
| `` <space> `` | チェックアウト | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: 現在のブランチにマージ
|
| `` n `` | 新しいブランチを作成 | |
|
||||||
<kbd>r</kbd>: Rebase checked-out branch onto this branch
|
| `` M `` | 現在のブランチにマージ | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: ブランチを削除
|
| `` r `` | Rebase | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: Set as upstream of checked-out branch
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
|
||||||
<kbd><enter></kbd>: コミットを閲覧
|
| `` s `` | 並び替え | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | コミットを閲覧 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 参照ログ
|
## 参照ログ
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: コミットのSHAをクリップボードにコピー
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: コミットをチェックアウト
|
| `` <c-o> `` | コミットのSHAをクリップボードにコピー | |
|
||||||
<kbd>y</kbd>: コミットの情報をコピー
|
| `` <space> `` | チェックアウト | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: ブラウザでコミットを開く
|
| `` y `` | コミットの情報をコピー | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: コミットにブランチを作成
|
| `` o `` | ブラウザでコミットを開く | |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` n `` | コミットにブランチを作成 | |
|
||||||
<kbd>c</kbd>: コミットをコピー (cherry-pick)
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: コミットを範囲コピー (cherry-pick)
|
| `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd><enter></kbd>: コミットを閲覧
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | コミットを閲覧 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 確認パネル
|
## 確認パネル
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 確認
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 閉じる/キャンセル
|
| `` <enter> `` | 確認 | |
|
||||||
</pre>
|
| `` <esc> `` | 閉じる/キャンセル | |
|
||||||
|
|||||||
+296
-266
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit 키 바인딩
|
# Lazygit 키 바인딩
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
|
|
||||||
## 글로벌 키 바인딩
|
## 글로벌 키 바인딩
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: 최근에 사용한 저장소로 전환
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: 메인 패널을 위로 스크롤 (fn+up/shift+k)
|
| `` <c-r> `` | 최근에 사용한 저장소로 전환 | |
|
||||||
<kbd><pgdown></kbd>: 메인 패널을 아래로로 스크롤 (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | 메인 패널을 위로 스크롤 | |
|
||||||
<kbd>@</kbd>: 명령어 로그 메뉴 열기
|
| `` <pgdown> (fn+down/shift+j) `` | 메인 패널을 아래로로 스크롤 | |
|
||||||
<kbd>}</kbd>: Diff 보기의 변경 사항 주위에 표시되는 컨텍스트의 크기를 늘리기
|
| `` @ `` | 명령어 로그 메뉴 열기 | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: Diff 보기의 변경 사항 주위에 표시되는 컨텍스트 크기 줄이기
|
| `` P `` | 푸시 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: Execute custom command
|
| `` p `` | 업데이트 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: 커스텀 Patch 옵션 보기
|
| `` } `` | Diff 보기의 변경 사항 주위에 표시되는 컨텍스트의 크기를 늘리기 | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: View merge/rebase options
|
| `` { `` | Diff 보기의 변경 사항 주위에 표시되는 컨텍스트 크기 줄이기 | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: 새로고침
|
| `` : `` | Execute custom command | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: 다음 스크린 모드 (normal/half/fullscreen)
|
| `` <c-p> `` | 커스텀 Patch 옵션 보기 | |
|
||||||
<kbd>_</kbd>: 이전 스크린 모드
|
| `` m `` | View merge/rebase options | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: 매뉴 열기
|
| `` R `` | 새로고침 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: View filter-by-path options
|
| `` + `` | 다음 스크린 모드 (normal/half/fullscreen) | |
|
||||||
<kbd>W</kbd>: Diff 메뉴 열기
|
| `` _ `` | 이전 스크린 모드 | |
|
||||||
<kbd><c-e></kbd>: Diff 메뉴 열기
|
| `` ? `` | 매뉴 열기 | |
|
||||||
<kbd><c-w></kbd>: 공백문자를 Diff 뷰에서 표시 여부 전환
|
| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: 되돌리기 (reflog) (실험적)
|
| `` W `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: 다시 실행 (reflog) (실험적)
|
| `` <c-e> `` | Diff 메뉴 열기 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: 푸시
|
| `` q `` | 종료 | |
|
||||||
<kbd>p</kbd>: 업데이트
|
| `` <esc> `` | 취소 | |
|
||||||
</pre>
|
| `` <c-w> `` | 공백문자를 Diff 뷰에서 표시 여부 전환 | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | 되돌리기 (reflog) (실험적) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
| `` <c-z> `` | 다시 실행 (reflog) (실험적) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
|
||||||
## List panel navigation
|
## List panel navigation
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: 이전 페이지
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: 다음 페이지
|
| `` , `` | 이전 페이지 | |
|
||||||
<kbd><</kbd>: 맨 위로 스크롤
|
| `` . `` | 다음 페이지 | |
|
||||||
<kbd>></kbd>: 맨 아래로 스크롤
|
| `` < `` | 맨 위로 스크롤 | |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` > `` | 맨 아래로 스크롤 | |
|
||||||
<kbd>H</kbd>: 우 스크롤
|
| `` v `` | 드래그 선택 전환 | |
|
||||||
<kbd>L</kbd>: 좌 스크롤
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: 이전 탭
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: 다음 탭
|
| `` / `` | 검색 시작 | |
|
||||||
</pre>
|
| `` H `` | 우 스크롤 | |
|
||||||
|
| `` L `` | 좌 스크롤 | |
|
||||||
|
| `` ] `` | 이전 탭 | |
|
||||||
|
| `` [ `` | 다음 탭 | |
|
||||||
|
|
||||||
## Reflog
|
## Reflog
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 커밋 SHA를 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 커밋을 체크아웃
|
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
|
||||||
<kbd>y</kbd>: 커밋 attribute 복사
|
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
| `` o `` | 브라우저에서 커밋 열기 | |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` n `` | 커밋에서 새 브랜치를 만듭니다. | |
|
||||||
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
|
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
|
| `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
|
||||||
<kbd><enter></kbd>: 커밋 보기
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 커밋 보기 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Stash
|
## Stash
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 적용
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: Pop
|
| `` <space> `` | 적용 | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: Drop
|
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: 새 브랜치 생성
|
| `` d `` | Drop | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Rename stash
|
| `` n `` | 새 브랜치 생성 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` r `` | Rename stash | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View selected item's files | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Sub-commits
|
## Sub-commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 커밋 SHA를 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 커밋을 체크아웃
|
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
|
||||||
<kbd>y</kbd>: 커밋 attribute 복사
|
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
| `` o `` | 브라우저에서 커밋 열기 | |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` n `` | 커밋에서 새 브랜치를 만듭니다. | |
|
||||||
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
|
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
|
| `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` <enter> `` | View selected item's files | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 검색 시작 | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 메뉴
|
## 메뉴
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 실행
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 닫기
|
| `` <enter> `` | 실행 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | 닫기 | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 메인 패널 (Merging)
|
## 메인 패널 (Merging)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: 파일 편집
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: 파일 닫기
|
| `` <space> `` | Pick hunk | |
|
||||||
<kbd><left></kbd>: 이전 충돌을 선택
|
| `` b `` | Pick all hunks | |
|
||||||
<kbd><right></kbd>: 다음 충돌을 선택
|
| `` <up> `` | 이전 hunk를 선택 | |
|
||||||
<kbd><up></kbd>: 이전 hunk를 선택
|
| `` <down> `` | 다음 hunk를 선택 | |
|
||||||
<kbd><down></kbd>: 다음 hunk를 선택
|
| `` <left> `` | 이전 충돌을 선택 | |
|
||||||
<kbd>z</kbd>: 되돌리기
|
| `` <right> `` | 다음 충돌을 선택 | |
|
||||||
<kbd>M</kbd>: Git mergetool를 열기
|
| `` z `` | 되돌리기 | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: Pick hunk
|
| `` e `` | 파일 편집 | Open file in external editor. |
|
||||||
<kbd>b</kbd>: Pick all hunks
|
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||||
<kbd><esc></kbd>: 파일 목록으로 돌아가기
|
| `` M `` | Git mergetool를 열기 | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | 파일 목록으로 돌아가기 | |
|
||||||
|
|
||||||
## 메인 패널 (Normal)
|
## 메인 패널 (Normal)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: 아래로 스크롤 (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: 위로 스크롤 (fn+down)
|
| `` mouse wheel down (fn+up) `` | 아래로 스크롤 | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | 위로 스크롤 | |
|
||||||
|
|
||||||
## 메인 패널 (Patch Building)
|
## 메인 패널 (Patch Building)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 이전 hunk를 선택
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 다음 hunk를 선택
|
| `` <left> `` | 이전 hunk를 선택 | |
|
||||||
<kbd>v</kbd>: 드래그 선택 전환
|
| `` <right> `` | 다음 hunk를 선택 | |
|
||||||
<kbd>V</kbd>: 드래그 선택 전환
|
| `` v `` | 드래그 선택 전환 | |
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
| `` a `` | Toggle select hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 선택한 텍스트를 클립보드에 복사
|
| `` <c-o> `` | 선택한 텍스트를 클립보드에 복사 | |
|
||||||
<kbd>o</kbd>: 파일 닫기
|
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||||
<kbd>e</kbd>: 파일 편집
|
| `` e `` | 파일 편집 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Line(s)을 패치에 추가/삭제
|
| `` <space> `` | Line(s)을 패치에 추가/삭제 | |
|
||||||
<kbd><esc></kbd>: Exit custom patch builder
|
| `` <esc> `` | Exit custom patch builder | |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` / `` | 검색 시작 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 메인 패널 (Staging)
|
## 메인 패널 (Staging)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 이전 hunk를 선택
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 다음 hunk를 선택
|
| `` <left> `` | 이전 hunk를 선택 | |
|
||||||
<kbd>v</kbd>: 드래그 선택 전환
|
| `` <right> `` | 다음 hunk를 선택 | |
|
||||||
<kbd>V</kbd>: 드래그 선택 전환
|
| `` v `` | 드래그 선택 전환 | |
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
| `` a `` | Toggle select hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 선택한 텍스트를 클립보드에 복사
|
| `` <c-o> `` | 선택한 텍스트를 클립보드에 복사 | |
|
||||||
<kbd>o</kbd>: 파일 닫기
|
| `` <space> `` | Staged 전환 | 선택한 행을 staged / unstaged |
|
||||||
<kbd>e</kbd>: 파일 편집
|
| `` d `` | 변경을 삭제 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: 파일 목록으로 돌아가기
|
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||||
<kbd><tab></kbd>: 패널 전환
|
| `` e `` | 파일 편집 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 선택한 행을 staged / unstaged
|
| `` <esc> `` | 파일 목록으로 돌아가기 | |
|
||||||
<kbd>d</kbd>: 변경을 삭제 (git reset)
|
| `` <tab> `` | 패널 전환 | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Edit hunk
|
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: 커밋 변경내용
|
| `` c `` | 커밋 변경내용 | Commit staged changes. |
|
||||||
<kbd>w</kbd>: Commit changes without pre-commit hook
|
| `` w `` | Commit changes without pre-commit hook | |
|
||||||
<kbd>C</kbd>: Git 편집기를 사용하여 변경 내용을 커밋합니다.
|
| `` C `` | Git 편집기를 사용하여 변경 내용을 커밋합니다. | |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` / `` | 검색 시작 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 브랜치
|
## 브랜치
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 브랜치명을 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: Git-flow 옵션 보기
|
| `` <c-o> `` | 브랜치명을 클립보드에 복사 | |
|
||||||
<kbd><space></kbd>: 체크아웃
|
| `` i `` | Git-flow 옵션 보기 | |
|
||||||
<kbd>n</kbd>: 새 브랜치 생성
|
| `` <space> `` | 체크아웃 | Checkout selected item. |
|
||||||
<kbd>o</kbd>: 풀 리퀘스트 생성
|
| `` n `` | 새 브랜치 생성 | |
|
||||||
<kbd>O</kbd>: 풀 리퀘스트 생성 옵션
|
| `` o `` | 풀 리퀘스트 생성 | |
|
||||||
<kbd><c-y></kbd>: 풀 리퀘스트 URL을 클립보드에 복사
|
| `` O `` | 풀 리퀘스트 생성 옵션 | |
|
||||||
<kbd>c</kbd>: 이름으로 체크아웃
|
| `` <c-y> `` | 풀 리퀘스트 URL을 클립보드에 복사 | |
|
||||||
<kbd>F</kbd>: 강제 체크아웃
|
| `` c `` | 이름으로 체크아웃 | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: 브랜치 삭제
|
| `` F `` | 강제 체크아웃 | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: 체크아웃된 브랜치를 이 브랜치에 리베이스
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: 현재 브랜치에 병합
|
| `` r `` | 체크아웃된 브랜치를 이 브랜치에 리베이스 | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: Fast-forward this branch from its upstream
|
| `` M `` | 현재 브랜치에 병합 | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: 태그를 생성
|
| `` f `` | Fast-forward this branch from its upstream | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` T `` | 태그를 생성 | |
|
||||||
<kbd>R</kbd>: 브랜치 이름 변경
|
| `` s `` | Sort order | |
|
||||||
<kbd>u</kbd>: Set/Unset upstream
|
| `` g `` | View reset options | |
|
||||||
<kbd><enter></kbd>: 커밋 보기
|
| `` R `` | 브랜치 이름 변경 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | 커밋 보기 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 상태
|
## 상태
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: 설정 파일 열기
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: 설정 파일 수정
|
| `` o `` | 설정 파일 열기 | Open file in default application. |
|
||||||
<kbd>u</kbd>: 업데이트 확인
|
| `` e `` | 설정 파일 수정 | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: 최근에 사용한 저장소로 전환
|
| `` u `` | 업데이트 확인 | |
|
||||||
<kbd>a</kbd>: 모든 브랜치 로그 표시
|
| `` <enter> `` | 최근에 사용한 저장소로 전환 | |
|
||||||
</pre>
|
| `` a `` | 모든 브랜치 로그 표시 | |
|
||||||
|
|
||||||
## 서브모듈
|
## 서브모듈
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 서브모듈 이름을 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: 서브모듈 열기
|
| `` <c-o> `` | 서브모듈 이름을 클립보드에 복사 | |
|
||||||
<kbd>d</kbd>: 서브모듈 삭제
|
| `` <enter> `` | Enter | 서브모듈 열기 |
|
||||||
<kbd>u</kbd>: 서브모듈 업데이트
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: 새로운 서브모듈 추가
|
| `` u `` | Update | 서브모듈 업데이트 |
|
||||||
<kbd>e</kbd>: 서브모듈의 URL을 수정
|
| `` n `` | 새로운 서브모듈 추가 | |
|
||||||
<kbd>i</kbd>: 서브모듈 초기화
|
| `` e `` | 서브모듈의 URL을 수정 | |
|
||||||
<kbd>b</kbd>: View bulk submodule options
|
| `` i `` | Initialize | 서브모듈 초기화 |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | View bulk submodule options | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 원격
|
## 원격
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: 원격을 업데이트
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: 새로운 Remote 추가
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: Remote를 삭제
|
| `` n `` | 새로운 Remote 추가 | |
|
||||||
<kbd>e</kbd>: Remote를 수정
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | Remote를 수정 |
|
||||||
</pre>
|
| `` f `` | Fetch | 원격을 업데이트 |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 원격 브랜치
|
## 원격 브랜치
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 브랜치명을 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 체크아웃
|
| `` <c-o> `` | 브랜치명을 클립보드에 복사 | |
|
||||||
<kbd>n</kbd>: 새 브랜치 생성
|
| `` <space> `` | 체크아웃 | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: 현재 브랜치에 병합
|
| `` n `` | 새 브랜치 생성 | |
|
||||||
<kbd>r</kbd>: 체크아웃된 브랜치를 이 브랜치에 리베이스
|
| `` M `` | 현재 브랜치에 병합 | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: 브랜치 삭제
|
| `` r `` | 체크아웃된 브랜치를 이 브랜치에 리베이스 | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: Set as upstream of checked-out branch
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
|
||||||
<kbd><enter></kbd>: 커밋 보기
|
| `` s `` | Sort order | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | 커밋 보기 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 커밋
|
## 커밋
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 커밋 SHA를 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-o> `` | 커밋 SHA를 클립보드에 복사 | |
|
||||||
<kbd>b</kbd>: Bisect 옵션 보기
|
| `` <c-r> `` | Reset cherry-picked (copied) commits selection | |
|
||||||
<kbd>s</kbd>: Squash down
|
| `` b `` | Bisect 옵션 보기 | |
|
||||||
<kbd>f</kbd>: Fixup commit
|
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: 커밋메시지 변경
|
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: 에디터에서 커밋메시지 수정
|
| `` r `` | 커밋메시지 변경 | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: 커밋 삭제
|
| `` R `` | 에디터에서 커밋메시지 수정 | |
|
||||||
<kbd>e</kbd>: 커밋을 편집
|
| `` d `` | 커밋 삭제 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: Pick commit (when mid-rebase)
|
| `` e `` | Edit (start interactive rebase) | 커밋을 편집 |
|
||||||
<kbd>F</kbd>: Create fixup commit for this commit
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: Squash all 'fixup!' commits above selected commit (autosquash)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: 커밋을 1개 아래로 이동
|
| `` p `` | Pick | Pick commit (when mid-rebase) |
|
||||||
<kbd><c-k></kbd>: 커밋을 1개 위로 이동
|
| `` F `` | Create fixup commit | Create fixup commit for this commit |
|
||||||
<kbd>v</kbd>: 커밋을 붙여넣기 (cherry-pick)
|
| `` S `` | Apply fixup commits | Squash all 'fixup!' commits above selected commit (autosquash) |
|
||||||
<kbd>A</kbd>: Amend commit with staged changes
|
| `` <c-j> `` | 커밋을 1개 아래로 이동 | |
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
| `` <c-k> `` | 커밋을 1개 위로 이동 | |
|
||||||
<kbd>t</kbd>: 커밋 되돌리기
|
| `` V `` | 커밋을 붙여넣기 (cherry-pick) | |
|
||||||
<kbd>T</kbd>: Tag commit
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: 로그 메뉴 열기
|
| `` A `` | Amend | Amend commit with staged changes |
|
||||||
<kbd><space></kbd>: 커밋을 체크아웃
|
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: 커밋 attribute 복사
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: 브라우저에서 커밋 열기
|
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: 커밋에서 새 브랜치를 만듭니다.
|
| `` <c-l> `` | 로그 메뉴 열기 | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` <space> `` | 체크아웃 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: 커밋을 복사 (cherry-pick)
|
| `` y `` | 커밋 attribute 복사 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: 커밋을 범위로 복사 (cherry-pick)
|
| `` o `` | 브라우저에서 커밋 열기 | |
|
||||||
<kbd><enter></kbd>: View selected item's files
|
| `` n `` | 커밋에서 새 브랜치를 만듭니다. | |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | View selected item's files | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 검색 시작 | |
|
||||||
|
|
||||||
## 커밋 파일
|
## 커밋 파일
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 커밋한 파일명을 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: Checkout file
|
| `` <c-o> `` | 파일명을 클립보드에 복사 | |
|
||||||
<kbd>d</kbd>: Discard this commit's changes to this file
|
| `` c `` | 체크아웃 | Checkout file |
|
||||||
<kbd>o</kbd>: 파일 닫기
|
| `` d `` | Remove | Discard this commit's changes to this file |
|
||||||
<kbd>e</kbd>: 파일 편집
|
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||||
<kbd><space></kbd>: Toggle file included in patch
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Toggle all files included in patch
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
|
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: 파일 트리뷰로 전환
|
| `` a `` | Toggle all files included in patch | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` <enter> `` | Enter file to add selected lines to the patch (or toggle directory collapsed) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | 파일 트리뷰로 전환 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | 검색 시작 | |
|
||||||
|
|
||||||
## 커밋메시지
|
## 커밋메시지
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 확인
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 닫기
|
| `` <enter> `` | 확인 | |
|
||||||
</pre>
|
| `` <esc> `` | 닫기 | |
|
||||||
|
|
||||||
## 태그
|
## 태그
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 체크아웃
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: 태그 삭제
|
| `` <space> `` | 체크아웃 | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: 태그를 push
|
| `` n `` | 태그를 생성 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: 태그를 생성
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: View reset options
|
| `` P `` | 태그를 push | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: 커밋 보기
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 커밋 보기 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 파일
|
## 파일
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 파일명을 클립보드에 복사
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: View 'discard changes' options
|
| `` <c-o> `` | 파일명을 클립보드에 복사 | |
|
||||||
<kbd><space></kbd>: Staged 전환
|
| `` <space> `` | Staged 전환 | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: 파일을 필터하기 (Staged/unstaged)
|
| `` <c-b> `` | 파일을 필터하기 (Staged/unstaged) | |
|
||||||
<kbd>c</kbd>: 커밋 변경내용
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: Commit changes without pre-commit hook
|
| `` c `` | 커밋 변경내용 | Commit staged changes. |
|
||||||
<kbd>A</kbd>: 마지맛 커밋 수정
|
| `` w `` | Commit changes without pre-commit hook | |
|
||||||
<kbd>C</kbd>: Git 편집기를 사용하여 변경 내용을 커밋합니다.
|
| `` A `` | 마지맛 커밋 수정 | |
|
||||||
<kbd>e</kbd>: 파일 편집
|
| `` C `` | Git 편집기를 사용하여 변경 내용을 커밋합니다. | |
|
||||||
<kbd>o</kbd>: 파일 닫기
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: Ignore file
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: 파일 새로고침
|
| `` o `` | 파일 닫기 | Open file in default application. |
|
||||||
<kbd>s</kbd>: 변경사항을 Stash
|
| `` i `` | Ignore file | |
|
||||||
<kbd>S</kbd>: Stash 옵션 보기
|
| `` r `` | 파일 새로고침 | |
|
||||||
<kbd>a</kbd>: 모든 변경을 Staged/unstaged으로 전환
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: Stage individual hunks/lines for file, or collapse/expand for directory
|
| `` S `` | Stash 옵션 보기 | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: View upstream reset options
|
| `` a `` | 모든 변경을 Staged/unstaged으로 전환 | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: View reset options
|
| `` <enter> `` | Stage individual hunks/lines for file, or collapse/expand for directory | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: 파일 트리뷰로 전환
|
| `` d `` | View 'discard changes' options | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: Git mergetool를 열기
|
| `` g `` | View upstream reset options | |
|
||||||
<kbd>f</kbd>: Fetch
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: 검색 시작
|
| `` ` `` | 파일 트리뷰로 전환 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | Git mergetool를 열기 | Run `git mergetool`. |
|
||||||
|
| `` f `` | Fetch | Fetch changes from remote. |
|
||||||
|
| `` / `` | 검색 시작 | |
|
||||||
|
|
||||||
## 확인 패널
|
## 확인 패널
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 확인
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 닫기/취소
|
| `` <enter> `` | 확인 | |
|
||||||
</pre>
|
| `` <esc> `` | 닫기/취소 | |
|
||||||
|
|||||||
+296
-266
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit Sneltoetsen
|
# Lazygit Sneltoetsen
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
|
|
||||||
## Globale sneltoetsen
|
## Globale sneltoetsen
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: Wissel naar een recente repo
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: Scroll naar beneden vanaf hoofdpaneel (fn+up/shift+k)
|
| `` <c-r> `` | Wissel naar een recente repo | |
|
||||||
<kbd><pgdown></kbd>: Scroll naar beneden vanaf hoofdpaneel (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | Scroll naar beneden vanaf hoofdpaneel | |
|
||||||
<kbd>@</kbd>: Open command log menu
|
| `` <pgdown> (fn+down/shift+j) `` | Scroll naar beneden vanaf hoofdpaneel | |
|
||||||
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
|
| `` @ `` | View command log options | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
|
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: Voer aangepaste commando uit
|
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: Bekijk aangepaste patch opties
|
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: Bekijk merge/rebase opties
|
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: Verversen
|
| `` : `` | Voer aangepaste commando uit | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: Volgende scherm modus (normaal/half/groot)
|
| `` <c-p> `` | Bekijk aangepaste patch opties | |
|
||||||
<kbd>_</kbd>: Vorige scherm modus
|
| `` m `` | Bekijk merge/rebase opties | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: Open menu
|
| `` R `` | Verversen | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: Bekijk scoping opties
|
| `` + `` | Volgende scherm modus (normaal/half/groot) | |
|
||||||
<kbd>W</kbd>: Open diff menu
|
| `` _ `` | Vorige scherm modus | |
|
||||||
<kbd><c-e></kbd>: Open diff menu
|
| `` ? `` | Open menu | |
|
||||||
<kbd><c-w></kbd>: Toggle whether or not whitespace changes are shown in the diff view
|
| `` <c-s> `` | Bekijk scoping opties | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: Ongedaan maken (via reflog) (experimenteel)
|
| `` W `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: Redo (via reflog) (experimenteel)
|
| `` <c-e> `` | Open diff menu | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: Push
|
| `` q `` | Quit | |
|
||||||
<kbd>p</kbd>: Pull
|
| `` <esc> `` | Annuleren | |
|
||||||
</pre>
|
| `` <c-w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | Ongedaan maken (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
| `` <c-z> `` | Redo (via reflog) (experimenteel) | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
|
||||||
## Lijstpaneel navigatie
|
## Lijstpaneel navigatie
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: Vorige pagina
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: Volgende pagina
|
| `` , `` | Vorige pagina | |
|
||||||
<kbd><</kbd>: Scroll naar boven
|
| `` . `` | Volgende pagina | |
|
||||||
<kbd>></kbd>: Scroll naar beneden
|
| `` < `` | Scroll naar boven | |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` > `` | Scroll naar beneden | |
|
||||||
<kbd>H</kbd>: Scroll left
|
| `` v `` | Toggle drag selecteer | |
|
||||||
<kbd>L</kbd>: Scroll right
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: Volgende tabblad
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: Vorige tabblad
|
| `` / `` | Start met zoeken | |
|
||||||
</pre>
|
| `` H `` | Scroll left | |
|
||||||
|
| `` L `` | Scroll right | |
|
||||||
|
| `` ] `` | Volgende tabblad | |
|
||||||
|
| `` [ `` | Vorige tabblad | |
|
||||||
|
|
||||||
## Bestanden
|
## Bestanden
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer de bestandsnaam naar het klembord
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Bekijk 'veranderingen ongedaan maken' opties
|
| `` <c-o> `` | Kopieer de bestandsnaam naar het klembord | |
|
||||||
<kbd><space></kbd>: Toggle staged
|
| `` <space> `` | Toggle staged | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: Filter files by status
|
| `` <c-b> `` | Filter files by status | |
|
||||||
<kbd>c</kbd>: Commit veranderingen
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: Commit veranderingen zonder pre-commit hook
|
| `` c `` | Commit veranderingen | Commit staged changes. |
|
||||||
<kbd>A</kbd>: Wijzig laatste commit
|
| `` w `` | Commit veranderingen zonder pre-commit hook | |
|
||||||
<kbd>C</kbd>: Commit veranderingen met de git editor
|
| `` A `` | Wijzig laatste commit | |
|
||||||
<kbd>e</kbd>: Verander bestand
|
| `` C `` | Commit veranderingen met de git editor | |
|
||||||
<kbd>o</kbd>: Open bestand
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: Ignore or exclude file
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: Refresh bestanden
|
| `` o `` | Open bestand | Open file in default application. |
|
||||||
<kbd>s</kbd>: Stash-bestanden
|
| `` i `` | Ignore or exclude file | |
|
||||||
<kbd>S</kbd>: Bekijk stash opties
|
| `` r `` | Refresh bestanden | |
|
||||||
<kbd>a</kbd>: Toggle staged alle
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: Stage individuele hunks/lijnen
|
| `` S `` | Bekijk stash opties | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: Bekijk upstream reset opties
|
| `` a `` | Toggle staged alle | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: Bekijk reset opties
|
| `` <enter> `` | Stage individuele hunks/lijnen | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: Toggle bestandsboom weergave
|
| `` d `` | Bekijk 'veranderingen ongedaan maken' opties | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: Open external merge tool (git mergetool)
|
| `` g `` | Bekijk upstream reset opties | |
|
||||||
<kbd>f</kbd>: Fetch
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` ` `` | Toggle bestandsboom weergave | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | Open external merge tool | Run `git mergetool`. |
|
||||||
|
| `` f `` | Fetch | Fetch changes from remote. |
|
||||||
|
| `` / `` | Start met zoeken | |
|
||||||
|
|
||||||
## Bevestigingspaneel
|
## Bevestigingspaneel
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Bevestig
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Sluiten
|
| `` <enter> `` | Bevestig | |
|
||||||
</pre>
|
| `` <esc> `` | Sluiten | |
|
||||||
|
|
||||||
## Branches
|
## Branches
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer branch name naar klembord
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: Laat git-flow opties zien
|
| `` <c-o> `` | Kopieer branch name naar klembord | |
|
||||||
<kbd><space></kbd>: Uitchecken
|
| `` i `` | Laat git-flow opties zien | |
|
||||||
<kbd>n</kbd>: Nieuwe branch
|
| `` <space> `` | Uitchecken | Checkout selected item. |
|
||||||
<kbd>o</kbd>: Maak een pull-request
|
| `` n `` | Nieuwe branch | |
|
||||||
<kbd>O</kbd>: Bekijk opties voor pull-aanvraag
|
| `` o `` | Maak een pull-request | |
|
||||||
<kbd><c-y></kbd>: Kopieer de URL van het pull-verzoek naar het klembord
|
| `` O `` | Bekijk opties voor pull-aanvraag | |
|
||||||
<kbd>c</kbd>: Uitchecken bij naam
|
| `` <c-y> `` | Kopieer de URL van het pull-verzoek naar het klembord | |
|
||||||
<kbd>F</kbd>: Forceer checkout
|
| `` c `` | Uitchecken bij naam | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: Verwijder branch
|
| `` F `` | Forceer checkout | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: Rebase branch
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: Merge in met huidige checked out branch
|
| `` r `` | Rebase branch | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: Fast-forward deze branch vanaf zijn upstream
|
| `` M `` | Merge in met huidige checked out branch | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: Creëer tag
|
| `` f `` | Fast-forward deze branch vanaf zijn upstream | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
| `` T `` | Creëer tag | |
|
||||||
<kbd>R</kbd>: Hernoem branch
|
| `` s `` | Sort order | |
|
||||||
<kbd>u</kbd>: Set/Unset upstream
|
| `` g `` | Bekijk reset opties | |
|
||||||
<kbd><enter></kbd>: Bekijk commits
|
| `` R `` | Hernoem branch | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | Bekijk commits | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Commit bericht
|
## Commit bericht
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Bevestig
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Sluiten
|
| `` <enter> `` | Bevestig | |
|
||||||
</pre>
|
| `` <esc> `` | Sluiten | |
|
||||||
|
|
||||||
## Commit bestanden
|
## Commit bestanden
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer de vastgelegde bestandsnaam naar het klembord
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: Bestand uitchecken
|
| `` <c-o> `` | Kopieer de bestandsnaam naar het klembord | |
|
||||||
<kbd>d</kbd>: Uitsluit deze commit zijn veranderingen aan dit bestand
|
| `` c `` | Uitchecken | Bestand uitchecken |
|
||||||
<kbd>o</kbd>: Open bestand
|
| `` d `` | Remove | Uitsluit deze commit zijn veranderingen aan dit bestand |
|
||||||
<kbd>e</kbd>: Verander bestand
|
| `` o `` | Open bestand | Open file in default application. |
|
||||||
<kbd><space></kbd>: Toggle bestand inbegrepen in patch
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Toggle all files included in patch
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: Enter bestand om geselecteerde regels toe te voegen aan de patch
|
| `` <space> `` | Toggle bestand inbegrepen in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: Toggle bestandsboom weergave
|
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` <enter> `` | Enter bestand om geselecteerde regels toe te voegen aan de patch | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | Toggle bestandsboom weergave | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | Start met zoeken | |
|
||||||
|
|
||||||
## Commits
|
## Commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer commit SHA naar klembord
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
|
||||||
<kbd>b</kbd>: View bisect options
|
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
|
||||||
<kbd>s</kbd>: Squash beneden
|
| `` b `` | View bisect options | |
|
||||||
<kbd>f</kbd>: Fixup commit
|
| `` s `` | Squash | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: Hernoem commit
|
| `` f `` | Fixup | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: Hernoem commit met editor
|
| `` r `` | Hernoem commit | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: Verwijder commit
|
| `` R `` | Hernoem commit met editor | |
|
||||||
<kbd>e</kbd>: Wijzig commit
|
| `` d `` | Verwijder commit | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: Kies commit (wanneer midden in rebase)
|
| `` e `` | Edit (start interactive rebase) | Wijzig commit |
|
||||||
<kbd>F</kbd>: Creëer fixup commit
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: Squash bovenstaande commits
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: Verplaats commit 1 naar beneden
|
| `` p `` | Pick | Kies commit (wanneer midden in rebase) |
|
||||||
<kbd><c-k></kbd>: Verplaats commit 1 naar boven
|
| `` F `` | Create fixup commit | Creëer fixup commit |
|
||||||
<kbd>v</kbd>: Plak commits (cherry-pick)
|
| `` S `` | Apply fixup commits | Squash bovenstaande commits |
|
||||||
<kbd>A</kbd>: Wijzig commit met staged veranderingen
|
| `` <c-j> `` | Verplaats commit 1 naar beneden | |
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
| `` <c-k> `` | Verplaats commit 1 naar boven | |
|
||||||
<kbd>t</kbd>: Commit ongedaan maken
|
| `` V `` | Plak commits (cherry-pick) | |
|
||||||
<kbd>T</kbd>: Tag commit
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: Open log menu
|
| `` A `` | Amend | Wijzig commit met staged veranderingen |
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
| `` <c-l> `` | View log options | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: Kopieer commit (cherry-pick)
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
| `` n `` | Creëer nieuwe branch van commit | |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | Bekijk gecommite bestanden | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Start met zoeken | |
|
||||||
|
|
||||||
## Menu
|
## Menu
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Uitvoeren
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Sluiten
|
| `` <enter> `` | Uitvoeren | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | Sluiten | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Mergen
|
## Mergen
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: Verander bestand
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: Open bestand
|
| `` <space> `` | Kies stuk | |
|
||||||
<kbd><left></kbd>: Selecteer voorgaand conflict
|
| `` b `` | Kies beide stukken | |
|
||||||
<kbd><right></kbd>: Selecteer volgende conflict
|
| `` <up> `` | Selecteer bovenste hunk | |
|
||||||
<kbd><up></kbd>: Selecteer bovenste hunk
|
| `` <down> `` | Selecteer onderste hunk | |
|
||||||
<kbd><down></kbd>: Selecteer onderste hunk
|
| `` <left> `` | Selecteer voorgaand conflict | |
|
||||||
<kbd>z</kbd>: Ongedaan maken
|
| `` <right> `` | Selecteer volgende conflict | |
|
||||||
<kbd>M</kbd>: Open external merge tool (git mergetool)
|
| `` z `` | Ongedaan maken | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: Kies stuk
|
| `` e `` | Verander bestand | Open file in external editor. |
|
||||||
<kbd>b</kbd>: Kies beide stukken
|
| `` o `` | Open bestand | Open file in default application. |
|
||||||
<kbd><esc></kbd>: Ga terug naar het bestanden paneel
|
| `` M `` | Open external merge tool | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | Ga terug naar het bestanden paneel | |
|
||||||
|
|
||||||
## Normaal
|
## Normaal
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: Scroll omlaag (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: Scroll omhoog (fn+down)
|
| `` mouse wheel down (fn+up) `` | Scroll omlaag | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | Scroll omhoog | |
|
||||||
|
|
||||||
## Patch bouwen
|
## Patch bouwen
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Selecteer de vorige hunk
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Selecteer de volgende hunk
|
| `` <left> `` | Selecteer de vorige hunk | |
|
||||||
<kbd>v</kbd>: Toggle drag selecteer
|
| `` <right> `` | Selecteer de volgende hunk | |
|
||||||
<kbd>V</kbd>: Toggle drag selecteer
|
| `` v `` | Toggle drag selecteer | |
|
||||||
<kbd>a</kbd>: Toggle selecteer hunk
|
| `` a `` | Toggle selecteer hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
| `` <c-o> `` | Copy selected text to clipboard | |
|
||||||
<kbd>o</kbd>: Open bestand
|
| `` o `` | Open bestand | Open file in default application. |
|
||||||
<kbd>e</kbd>: Verander bestand
|
| `` e `` | Verander bestand | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Voeg toe/verwijder lijn(en) in patch
|
| `` <space> `` | Voeg toe/verwijder lijn(en) in patch | |
|
||||||
<kbd><esc></kbd>: Sluit lijn-bij-lijn modus
|
| `` <esc> `` | Sluit lijn-bij-lijn modus | |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` / `` | Start met zoeken | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Reflog
|
## Reflog
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer commit SHA naar klembord
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
| `` n `` | Creëer nieuwe branch van commit | |
|
||||||
<kbd>c</kbd>: Kopieer commit (cherry-pick)
|
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
|
| `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
|
||||||
<kbd><enter></kbd>: Bekijk commits
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Bekijk commits | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Remote branches
|
## Remote branches
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer branch name naar klembord
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Uitchecken
|
| `` <c-o> `` | Kopieer branch name naar klembord | |
|
||||||
<kbd>n</kbd>: Nieuwe branch
|
| `` <space> `` | Uitchecken | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: Merge in met huidige checked out branch
|
| `` n `` | Nieuwe branch | |
|
||||||
<kbd>r</kbd>: Rebase branch
|
| `` M `` | Merge in met huidige checked out branch | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: Verwijder branch
|
| `` r `` | Rebase branch | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: Stel in als upstream van uitgecheckte branch
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
| `` u `` | Set as upstream | Stel in als upstream van uitgecheckte branch |
|
||||||
<kbd><enter></kbd>: Bekijk commits
|
| `` s `` | Sort order | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | Bekijk commits | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Remotes
|
## Remotes
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: Fetch remote
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: Voeg een nieuwe remote toe
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: Verwijder remote
|
| `` n `` | Voeg een nieuwe remote toe | |
|
||||||
<kbd>e</kbd>: Wijzig remote
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | Wijzig remote |
|
||||||
</pre>
|
| `` f `` | Fetch | Fetch remote |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Staging
|
## Staging
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Selecteer de vorige hunk
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Selecteer de volgende hunk
|
| `` <left> `` | Selecteer de vorige hunk | |
|
||||||
<kbd>v</kbd>: Toggle drag selecteer
|
| `` <right> `` | Selecteer de volgende hunk | |
|
||||||
<kbd>V</kbd>: Toggle drag selecteer
|
| `` v `` | Toggle drag selecteer | |
|
||||||
<kbd>a</kbd>: Toggle selecteer hunk
|
| `` a `` | Toggle selecteer hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
| `` <c-o> `` | Copy selected text to clipboard | |
|
||||||
<kbd>o</kbd>: Open bestand
|
| `` <space> `` | Toggle staged | Toggle lijnen staged / unstaged |
|
||||||
<kbd>e</kbd>: Verander bestand
|
| `` d `` | Verwijdert change (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: Ga terug naar het bestanden paneel
|
| `` o `` | Open bestand | Open file in default application. |
|
||||||
<kbd><tab></kbd>: Ga naar een ander paneel
|
| `` e `` | Verander bestand | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Toggle lijnen staged / unstaged
|
| `` <esc> `` | Ga terug naar het bestanden paneel | |
|
||||||
<kbd>d</kbd>: Verwijdert change (git reset)
|
| `` <tab> `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Edit hunk
|
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: Commit veranderingen
|
| `` c `` | Commit veranderingen | Commit staged changes. |
|
||||||
<kbd>w</kbd>: Commit veranderingen zonder pre-commit hook
|
| `` w `` | Commit veranderingen zonder pre-commit hook | |
|
||||||
<kbd>C</kbd>: Commit veranderingen met de git editor
|
| `` C `` | Commit veranderingen met de git editor | |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` / `` | Start met zoeken | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Stash
|
## Stash
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Toepassen
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: Pop
|
| `` <space> `` | Toepassen | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: Laten vallen
|
| `` g `` | Pop | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: Nieuwe branch
|
| `` d `` | Laten vallen | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Rename stash
|
| `` n `` | Nieuwe branch | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
| `` r `` | Rename stash | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Bekijk gecommite bestanden | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: Open config bestand
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: Verander config bestand
|
| `` o `` | Open config bestand | Open file in default application. |
|
||||||
<kbd>u</kbd>: Check voor updates
|
| `` e `` | Verander config bestand | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: Wissel naar een recente repo
|
| `` u `` | Check voor updates | |
|
||||||
<kbd>a</kbd>: Alle logs van de branch laten zien
|
| `` <enter> `` | Wissel naar een recente repo | |
|
||||||
</pre>
|
| `` a `` | Alle logs van de branch laten zien | |
|
||||||
|
|
||||||
## Sub-commits
|
## Sub-commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer commit SHA naar klembord
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` <c-o> `` | Kopieer commit SHA naar klembord | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | Uitchecken | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Creëer nieuwe branch van commit
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
| `` n `` | Creëer nieuwe branch van commit | |
|
||||||
<kbd>c</kbd>: Kopieer commit (cherry-pick)
|
| `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Kopieer commit reeks (cherry-pick)
|
| `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (gekopieerde) commits selectie
|
| `` <c-r> `` | Reset cherry-picked (gekopieerde) commits selectie | |
|
||||||
<kbd><enter></kbd>: Bekijk gecommite bestanden
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Start met zoeken
|
| `` <enter> `` | Bekijk gecommite bestanden | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Start met zoeken | |
|
||||||
|
|
||||||
## Submodules
|
## Submodules
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Kopieer submodule naam naar klembord
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: Enter submodule
|
| `` <c-o> `` | Kopieer submodule naam naar klembord | |
|
||||||
<kbd>d</kbd>: Remove submodule
|
| `` <enter> `` | Enter | Enter submodule |
|
||||||
<kbd>u</kbd>: Update submodule
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: Voeg nieuwe submodule toe
|
| `` u `` | Update | Update selected submodule. |
|
||||||
<kbd>e</kbd>: Update submodule URL
|
| `` n `` | Voeg nieuwe submodule toe | |
|
||||||
<kbd>i</kbd>: Initialiseer submodule
|
| `` e `` | Update submodule URL | |
|
||||||
<kbd>b</kbd>: Bekijk bulk submodule opties
|
| `` i `` | Initialize | Initialiseer submodule |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | Bekijk bulk submodule opties | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Tags
|
## Tags
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Uitchecken
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Verwijder tag
|
| `` <space> `` | Uitchecken | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: Push tag
|
| `` n `` | Creëer tag | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Creëer tag
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: Bekijk reset opties
|
| `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: Bekijk commits
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Bekijk commits | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|||||||
+296
-266
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit Keybindings
|
# Lazygit Keybindings
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
|
|
||||||
## Globalne
|
## Globalne
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: Switch to a recent repo
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: Scroll up main panel (fn+up/shift+k)
|
| `` <c-r> `` | Switch to a recent repo | |
|
||||||
<kbd><pgdown></kbd>: Scroll down main panel (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | Scroll up main window | |
|
||||||
<kbd>@</kbd>: Open command log menu
|
| `` <pgdown> (fn+down/shift+j) `` | Scroll down main window | |
|
||||||
<kbd>}</kbd>: Increase the size of the context shown around changes in the diff view
|
| `` @ `` | View command log options | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: Decrease the size of the context shown around changes in the diff view
|
| `` P `` | Push | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: Wykonaj własną komendę
|
| `` p `` | Pull | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: View custom patch options
|
| `` } `` | Increase diff context size | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: Widok scalenia/opcje zmiany bazy
|
| `` { `` | Decrease diff context size | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: Odśwież
|
| `` : `` | Wykonaj własną komendę | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: Next screen mode (normal/half/fullscreen)
|
| `` <c-p> `` | View custom patch options | |
|
||||||
<kbd>_</kbd>: Prev screen mode
|
| `` m `` | Widok scalenia/opcje zmiany bazy | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: Open menu
|
| `` R `` | Odśwież | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: View filter-by-path options
|
| `` + `` | Next screen mode (normal/half/fullscreen) | |
|
||||||
<kbd>W</kbd>: Open diff menu
|
| `` _ `` | Prev screen mode | |
|
||||||
<kbd><c-e></kbd>: Open diff menu
|
| `` ? `` | Open keybindings menu | |
|
||||||
<kbd><c-w></kbd>: Toggle whether or not whitespace changes are shown in the diff view
|
| `` <c-s> `` | View filter-by-path options | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: Undo
|
| `` W `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: Redo
|
| `` <c-e> `` | View diffing options | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: Push
|
| `` q `` | Quit | |
|
||||||
<kbd>p</kbd>: Pull
|
| `` <esc> `` | Anuluj | |
|
||||||
</pre>
|
| `` <c-w> `` | Toggle whitespace | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | Undo | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
| `` <c-z> `` | Redo | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
|
||||||
## List panel navigation
|
## List panel navigation
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: Previous page
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: Next page
|
| `` , `` | Previous page | |
|
||||||
<kbd><</kbd>: Scroll to top
|
| `` . `` | Next page | |
|
||||||
<kbd>></kbd>: Scroll to bottom
|
| `` < `` | Scroll to top | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` > `` | Scroll to bottom | |
|
||||||
<kbd>H</kbd>: Scroll left
|
| `` v `` | Toggle range select | |
|
||||||
<kbd>L</kbd>: Scroll right
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: Next tab
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: Previous tab
|
| `` / `` | Search the current view by text | |
|
||||||
</pre>
|
| `` H `` | Scroll left | |
|
||||||
|
| `` L `` | Scroll right | |
|
||||||
|
| `` ] `` | Next tab | |
|
||||||
|
| `` [ `` | Previous tab | |
|
||||||
|
|
||||||
## Commit summary
|
## Commit summary
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Potwierdź
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Zamknij
|
| `` <enter> `` | Potwierdź | |
|
||||||
</pre>
|
| `` <esc> `` | Zamknij | |
|
||||||
|
|
||||||
## Commity
|
## Commity
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy commit SHA to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||||
<kbd>b</kbd>: View bisect options
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd>s</kbd>: Ściśnij
|
| `` b `` | View bisect options | |
|
||||||
<kbd>f</kbd>: Napraw commit
|
| `` s `` | Spłaszcz | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: Zmień nazwę commita
|
| `` f `` | Napraw | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: Zmień nazwę commita w edytorze
|
| `` r `` | Zmień nazwę commita | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: Usuń commit
|
| `` R `` | Zmień nazwę commita w edytorze | |
|
||||||
<kbd>e</kbd>: Edytuj commit
|
| `` d `` | Usuń commit | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: Wybierz commit (podczas zmiany bazy)
|
| `` e `` | Edit (start interactive rebase) | Edytuj commit |
|
||||||
<kbd>F</kbd>: Utwórz commit naprawczy dla tego commita
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: Spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: Przenieś commit 1 w dół
|
| `` p `` | Pick | Wybierz commit (podczas zmiany bazy) |
|
||||||
<kbd><c-k></kbd>: Przenieś commit 1 w górę
|
| `` F `` | Create fixup commit | Utwórz commit naprawczy dla tego commita |
|
||||||
<kbd>v</kbd>: Wklej commity (przebieranie)
|
| `` S `` | Apply fixup commits | Spłaszcz wszystkie commity naprawcze powyżej zaznaczonych commitów (autosquash) |
|
||||||
<kbd>A</kbd>: Popraw commit zmianami z poczekalni
|
| `` <c-j> `` | Przenieś commit 1 w dół | |
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
| `` <c-k> `` | Przenieś commit 1 w górę | |
|
||||||
<kbd>t</kbd>: Odwróć commit
|
| `` V `` | Wklej commity (przebieranie) | |
|
||||||
<kbd>T</kbd>: Tag commit
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: Open log menu
|
| `` A `` | Amend | Popraw commit zmianami z poczekalni |
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` T `` | Tag commit | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
| `` <c-l> `` | View log options | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
| `` <space> `` | Przełącz | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: Kopiuj commit (przebieranie)
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd><enter></kbd>: Przeglądaj pliki commita
|
| `` n `` | Create new branch off of commit | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` g `` | Wyświetl opcje resetu | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | Kopiuj commit (przebieranie) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | Przeglądaj pliki commita | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Confirmation panel
|
## Confirmation panel
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Potwierdź
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Zamknij
|
| `` <enter> `` | Potwierdź | |
|
||||||
</pre>
|
| `` <esc> `` | Zamknij | |
|
||||||
|
|
||||||
## Local branches
|
## Local branches
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy branch name to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: Show git-flow options
|
| `` <c-o> `` | Copy branch name to clipboard | |
|
||||||
<kbd><space></kbd>: Przełącz
|
| `` i `` | Show git-flow options | |
|
||||||
<kbd>n</kbd>: Nowa gałąź
|
| `` <space> `` | Przełącz | Checkout selected item. |
|
||||||
<kbd>o</kbd>: Utwórz żądanie pobrania
|
| `` n `` | Nowa gałąź | |
|
||||||
<kbd>O</kbd>: Utwórz opcje żądania ściągnięcia
|
| `` o `` | Utwórz żądanie pobrania | |
|
||||||
<kbd><c-y></kbd>: Skopiuj adres URL żądania pobrania do schowka
|
| `` O `` | Utwórz opcje żądania ściągnięcia | |
|
||||||
<kbd>c</kbd>: Przełącz używając nazwy
|
| `` <c-y> `` | Skopiuj adres URL żądania pobrania do schowka | |
|
||||||
<kbd>F</kbd>: Wymuś przełączenie
|
| `` c `` | Przełącz używając nazwy | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: Usuń gałąź
|
| `` F `` | Wymuś przełączenie | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: Zmiana bazy gałęzi
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: Scal do obecnej gałęzi
|
| `` r `` | Zmiana bazy gałęzi | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: Fast-forward this branch from its upstream
|
| `` M `` | Scal do obecnej gałęzi | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: Create tag
|
| `` f `` | Fast-forward | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
| `` T `` | New tag | |
|
||||||
<kbd>R</kbd>: Rename branch
|
| `` s `` | Sort order | |
|
||||||
<kbd>u</kbd>: Set/Unset upstream
|
| `` g `` | Wyświetl opcje resetu | |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` R `` | Rename branch | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | View commits | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Main panel (patch building)
|
## Main panel (patch building)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Poprzedni kawałek
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Następny kawałek
|
| `` <left> `` | Poprzedni kawałek | |
|
||||||
<kbd>v</kbd>: Toggle drag select
|
| `` <right> `` | Następny kawałek | |
|
||||||
<kbd>V</kbd>: Toggle drag select
|
| `` v `` | Toggle range select | |
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
| `` a `` | Select hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
| `` <c-o> `` | Copy selected text to clipboard | |
|
||||||
<kbd>o</kbd>: Otwórz plik
|
| `` o `` | Otwórz plik | Open file in default application. |
|
||||||
<kbd>e</kbd>: Edytuj plik
|
| `` e `` | Edytuj plik | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Add/Remove line(s) to patch
|
| `` <space> `` | Toggle lines in patch | |
|
||||||
<kbd><esc></kbd>: Wyście z trybu "linia po linii"
|
| `` <esc> `` | Wyście z trybu "linia po linii" | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` / `` | Search the current view by text | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Menu
|
## Menu
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Wykonaj
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Zamknij
|
| `` <enter> `` | Wykonaj | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | Zamknij | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Pliki
|
## Pliki
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy the file name to the clipboard
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Pokaż opcje porzucania zmian
|
| `` <c-o> `` | Copy path to clipboard | |
|
||||||
<kbd><space></kbd>: Przełącz stan poczekalni
|
| `` <space> `` | Przełącz stan poczekalni | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: Filter files by status
|
| `` <c-b> `` | Filter files by status | |
|
||||||
<kbd>c</kbd>: Zatwierdź zmiany
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: Zatwierdź zmiany bez skryptu pre-commit
|
| `` c `` | Zatwierdź zmiany | Commit staged changes. |
|
||||||
<kbd>A</kbd>: Zmień ostatni commit
|
| `` w `` | Zatwierdź zmiany bez skryptu pre-commit | |
|
||||||
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
|
| `` A `` | Zmień ostatni commit | |
|
||||||
<kbd>e</kbd>: Edytuj plik
|
| `` C `` | Zatwierdź zmiany używając edytora | |
|
||||||
<kbd>o</kbd>: Otwórz plik
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: Ignore or exclude file
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: Odśwież pliki
|
| `` o `` | Otwórz plik | Open file in default application. |
|
||||||
<kbd>s</kbd>: Przechowaj zmiany
|
| `` i `` | Ignore or exclude file | |
|
||||||
<kbd>S</kbd>: Wyświetl opcje schowka
|
| `` r `` | Odśwież pliki | |
|
||||||
<kbd>a</kbd>: Przełącz stan poczekalni wszystkich
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: Zatwierdź pojedyncze linie
|
| `` S `` | Wyświetl opcje schowka | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: View upstream reset options
|
| `` a `` | Przełącz stan poczekalni wszystkich | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: Wyświetl opcje resetu
|
| `` <enter> `` | Zatwierdź pojedyncze linie | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: Toggle file tree view
|
| `` d `` | Pokaż opcje porzucania zmian | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: Open external merge tool (git mergetool)
|
| `` g `` | View upstream reset options | |
|
||||||
<kbd>f</kbd>: Pobierz
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | Open external merge tool | Run `git mergetool`. |
|
||||||
|
| `` f `` | Pobierz | Fetch changes from remote. |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Pliki commita
|
## Pliki commita
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy the committed file name to the clipboard
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: Plik wybierania
|
| `` <c-o> `` | Copy path to clipboard | |
|
||||||
<kbd>d</kbd>: Porzuć zmiany commita dla tego pliku
|
| `` c `` | Przełącz | Plik wybierania |
|
||||||
<kbd>o</kbd>: Otwórz plik
|
| `` d `` | Remove | Porzuć zmiany commita dla tego pliku |
|
||||||
<kbd>e</kbd>: Edytuj plik
|
| `` o `` | Otwórz plik | Open file in default application. |
|
||||||
<kbd><space></kbd>: Toggle file included in patch
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Toggle all files included in patch
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: Enter file to add selected lines to the patch (or toggle directory collapsed)
|
| `` <space> `` | Toggle file included in patch | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: Toggle file tree view
|
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` <enter> `` | Enter file / Toggle directory collapsed | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Poczekalnia
|
## Poczekalnia
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Poprzedni kawałek
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Następny kawałek
|
| `` <left> `` | Poprzedni kawałek | |
|
||||||
<kbd>v</kbd>: Toggle drag select
|
| `` <right> `` | Następny kawałek | |
|
||||||
<kbd>V</kbd>: Toggle drag select
|
| `` v `` | Toggle range select | |
|
||||||
<kbd>a</kbd>: Toggle select hunk
|
| `` a `` | Select hunk | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Copy the selected text to the clipboard
|
| `` <c-o> `` | Copy selected text to clipboard | |
|
||||||
<kbd>o</kbd>: Otwórz plik
|
| `` <space> `` | Przełącz stan poczekalni | Toggle selection staged / unstaged. |
|
||||||
<kbd>e</kbd>: Edytuj plik
|
| `` d `` | Discard | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: Wróć do panelu plików
|
| `` o `` | Otwórz plik | Open file in default application. |
|
||||||
<kbd><tab></kbd>: Switch to other panel (staged/unstaged changes)
|
| `` e `` | Edytuj plik | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Toggle line staged / unstaged
|
| `` <esc> `` | Wróć do panelu plików | |
|
||||||
<kbd>d</kbd>: Discard change (git reset)
|
| `` <tab> `` | Switch view | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Edit hunk
|
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: Zatwierdź zmiany
|
| `` c `` | Zatwierdź zmiany | Commit staged changes. |
|
||||||
<kbd>w</kbd>: Zatwierdź zmiany bez skryptu pre-commit
|
| `` w `` | Zatwierdź zmiany bez skryptu pre-commit | |
|
||||||
<kbd>C</kbd>: Zatwierdź zmiany używając edytora
|
| `` C `` | Zatwierdź zmiany używając edytora | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` / `` | Search the current view by text | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Reflog
|
## Reflog
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy commit SHA to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | Przełącz | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
| `` n `` | Create new branch off of commit | |
|
||||||
<kbd>c</kbd>: Kopiuj commit (przebieranie)
|
| `` g `` | Wyświetl opcje resetu | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
|
| `` C `` | Kopiuj commit (przebieranie) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View commits | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Remote branches
|
## Remote branches
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy branch name to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Przełącz
|
| `` <c-o> `` | Copy branch name to clipboard | |
|
||||||
<kbd>n</kbd>: Nowa gałąź
|
| `` <space> `` | Przełącz | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: Scal do obecnej gałęzi
|
| `` n `` | Nowa gałąź | |
|
||||||
<kbd>r</kbd>: Zmiana bazy gałęzi
|
| `` M `` | Scal do obecnej gałęzi | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: Usuń gałąź
|
| `` r `` | Zmiana bazy gałęzi | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: Set as upstream of checked-out branch
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
| `` u `` | Set as upstream | Set the selected remote branch as the upstream of the checked-out branch. |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` s `` | Sort order | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | Wyświetl opcje resetu | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | View commits | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Remotes
|
## Remotes
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: Fetch remote
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: Add new remote
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: Remove remote
|
| `` n `` | New remote | |
|
||||||
<kbd>e</kbd>: Edit remote
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | Edit the selected remote's name or URL. |
|
||||||
</pre>
|
| `` f `` | Pobierz | Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Scalanie
|
## Scalanie
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: Edytuj plik
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: Otwórz plik
|
| `` <space> `` | Wybierz kawałek | |
|
||||||
<kbd><left></kbd>: Poprzedni konflikt
|
| `` b `` | Wybierz oba kawałki | |
|
||||||
<kbd><right></kbd>: Następny konflikt
|
| `` <up> `` | Wybierz poprzedni kawałek | |
|
||||||
<kbd><up></kbd>: Wybierz poprzedni kawałek
|
| `` <down> `` | Wybierz następny kawałek | |
|
||||||
<kbd><down></kbd>: Wybierz następny kawałek
|
| `` <left> `` | Poprzedni konflikt | |
|
||||||
<kbd>z</kbd>: Cofnij
|
| `` <right> `` | Następny konflikt | |
|
||||||
<kbd>M</kbd>: Open external merge tool (git mergetool)
|
| `` z `` | Cofnij | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: Wybierz kawałek
|
| `` e `` | Edytuj plik | Open file in external editor. |
|
||||||
<kbd>b</kbd>: Wybierz oba kawałki
|
| `` o `` | Otwórz plik | Open file in default application. |
|
||||||
<kbd><esc></kbd>: Wróć do panelu plików
|
| `` M `` | Open external merge tool | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | Wróć do panelu plików | |
|
||||||
|
|
||||||
## Schowek
|
## Schowek
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Zastosuj
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: Wyciągnij
|
| `` <space> `` | Zastosuj | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: Porzuć
|
| `` g `` | Wyciągnij | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: Nowa gałąź
|
| `` d `` | Porzuć | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Rename stash
|
| `` n `` | Nowa gałąź | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: Przeglądaj pliki commita
|
| `` r `` | Rename stash | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Przeglądaj pliki commita | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: Otwórz konfigurację
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: Edytuj konfigurację
|
| `` o `` | Otwórz konfigurację | Open file in default application. |
|
||||||
<kbd>u</kbd>: Sprawdź aktualizacje
|
| `` e `` | Edytuj konfigurację | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: Switch to a recent repo
|
| `` u `` | Sprawdź aktualizacje | |
|
||||||
<kbd>a</kbd>: Pokaż wszystkie logi gałęzi
|
| `` <enter> `` | Switch to a recent repo | |
|
||||||
</pre>
|
| `` a `` | Pokaż wszystkie logi gałęzi | |
|
||||||
|
|
||||||
## Sub-commits
|
## Sub-commits
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy commit SHA to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Checkout commit
|
| `` <c-o> `` | Copy commit SHA to clipboard | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | Przełącz | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Open commit in browser
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Create new branch off of commit
|
| `` o `` | Open commit in browser | |
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
| `` n `` | Create new branch off of commit | |
|
||||||
<kbd>c</kbd>: Kopiuj commit (przebieranie)
|
| `` g `` | Wyświetl opcje resetu | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Kopiuj zakres commitów (przebieranie)
|
| `` C `` | Kopiuj commit (przebieranie) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Reset cherry-picked (copied) commits selection
|
| `` <c-r> `` | Reset copied (cherry-picked) commits selection | |
|
||||||
<kbd><enter></kbd>: Przeglądaj pliki commita
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Search the current view by text
|
| `` <enter> `` | Przeglądaj pliki commita | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Search the current view by text | |
|
||||||
|
|
||||||
## Submodules
|
## Submodules
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Copy submodule name to clipboard
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: Enter submodule
|
| `` <c-o> `` | Copy submodule name to clipboard | |
|
||||||
<kbd>d</kbd>: Remove submodule
|
| `` <enter> `` | Enter | Enter submodule. After entering the submodule, you can press `<esc>` to escape back to the parent repo. |
|
||||||
<kbd>u</kbd>: Update submodule
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: Add new submodule
|
| `` u `` | Update | Update selected submodule. |
|
||||||
<kbd>e</kbd>: Update submodule URL
|
| `` n `` | New submodule | |
|
||||||
<kbd>i</kbd>: Initialize submodule
|
| `` e `` | Update submodule URL | |
|
||||||
<kbd>b</kbd>: View bulk submodule options
|
| `` i `` | Initialize | Initialize the selected submodule to prepare for fetching. You probably want to follow this up by invoking the 'update' action to fetch the submodule. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | View bulk submodule options | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Tags
|
## Tags
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Przełącz
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Delete tag
|
| `` <space> `` | Przełącz | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: Push tag
|
| `` n `` | New tag | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Create tag
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: Wyświetl opcje resetu
|
| `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: View commits
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | View commits | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Zwykłe
|
## Zwykłe
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: Przewiń w dół (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: Przewiń w górę (fn+down)
|
| `` mouse wheel down (fn+up) `` | Przewiń w dół | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | Przewiń w górę | |
|
||||||
|
|||||||
+296
-266
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit Связки клавиш
|
# Lazygit Связки клавиш
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Связки клавиш_
|
|||||||
|
|
||||||
## Глобальные сочетания клавиш
|
## Глобальные сочетания клавиш
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: Переключиться на последний репозиторий
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: Прокрутить вверх главную панель (fn+up/shift+k)
|
| `` <c-r> `` | Переключиться на последний репозиторий | |
|
||||||
<kbd><pgdown></kbd>: Прокрутить вниз главную панель (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | Прокрутить вверх главную панель | |
|
||||||
<kbd>@</kbd>: Открыть меню журнала команд
|
| `` <pgdown> (fn+down/shift+j) `` | Прокрутить вниз главную панель | |
|
||||||
<kbd>}</kbd>: Увеличить размер контекста, отображаемого вокруг изменений в просмотрщике сравнении
|
| `` @ `` | Открыть меню журнала команд | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: Уменьшите размер контекста, отображаемого вокруг изменений в просмотрщике сравнении
|
| `` P `` | Отправить изменения | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: Выполнить пользовательскую команду
|
| `` p `` | Получить и слить изменения | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: Просмотреть пользовательские параметры патча
|
| `` } `` | Увеличить размер контекста, отображаемого вокруг изменений в просмотрщике сравнении | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: Просмотреть параметры слияния/перебазирования
|
| `` { `` | Уменьшите размер контекста, отображаемого вокруг изменений в просмотрщике сравнении | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: Обновить
|
| `` : `` | Выполнить пользовательскую команду | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: Следующий режим экрана (нормальный/полуэкранный/полноэкранный)
|
| `` <c-p> `` | Просмотреть пользовательские параметры патча | |
|
||||||
<kbd>_</kbd>: Предыдущий режим экрана
|
| `` m `` | Просмотреть параметры слияния/перебазирования | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: Открыть меню
|
| `` R `` | Обновить | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: Просмотреть параметры фильтрации по пути
|
| `` + `` | Следующий режим экрана (нормальный/полуэкранный/полноэкранный) | |
|
||||||
<kbd>W</kbd>: Открыть меню сравнении
|
| `` _ `` | Предыдущий режим экрана | |
|
||||||
<kbd><c-e></kbd>: Открыть меню сравнении
|
| `` ? `` | Открыть меню | |
|
||||||
<kbd><c-w></kbd>: Переключить отображение изменении пробелов в просмотрщике сравнении
|
| `` <c-s> `` | Просмотреть параметры фильтрации по пути | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: Отменить (через reflog) (экспериментальный)
|
| `` W `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: Повторить (через reflog) (экспериментальный)
|
| `` <c-e> `` | Открыть меню сравнении | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: Отправить изменения
|
| `` q `` | Выйти | |
|
||||||
<kbd>p</kbd>: Получить и слить изменения
|
| `` <esc> `` | Отменить | |
|
||||||
</pre>
|
| `` <c-w> `` | Переключить отображение изменении пробелов в просмотрщике сравнении | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | Отменить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git запустить, чтобы отменить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. |
|
||||||
|
| `` <c-z> `` | Повторить (через reflog) (экспериментальный) | Журнал ссылок (reflog) будет использоваться для определения того, какую команду git нужно запустить, чтобы повторить последнюю команду git. Сюда не входят изменения в рабочем дереве; учитываются только коммиты. |
|
||||||
|
|
||||||
## Навигация по панели списка
|
## Навигация по панели списка
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: Предыдущая страница
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: Следующая страница
|
| `` , `` | Предыдущая страница | |
|
||||||
<kbd><</kbd>: Пролистать наверх
|
| `` . `` | Следующая страница | |
|
||||||
<kbd>></kbd>: Прокрутить вниз
|
| `` < `` | Пролистать наверх | |
|
||||||
<kbd>/</kbd>: Найти
|
| `` > `` | Прокрутить вниз | |
|
||||||
<kbd>H</kbd>: Прокрутить влево
|
| `` v `` | Переключить выборку перетаскивания | |
|
||||||
<kbd>L</kbd>: Прокрутить вправо
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: Следующая вкладка
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: Предыдущая вкладка
|
| `` / `` | Найти | |
|
||||||
</pre>
|
| `` H `` | Прокрутить влево | |
|
||||||
|
| `` L `` | Прокрутить вправо | |
|
||||||
|
| `` ] `` | Следующая вкладка | |
|
||||||
|
| `` [ `` | Предыдущая вкладка | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Главная панель (Индексирование)
|
## Главная панель (Индексирование)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Выбрать предыдущую часть
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Выбрать следующую часть
|
| `` <left> `` | Выбрать предыдущую часть | |
|
||||||
<kbd>v</kbd>: Переключить выборку перетаскивания
|
| `` <right> `` | Выбрать следующую часть | |
|
||||||
<kbd>V</kbd>: Переключить выборку перетаскивания
|
| `` v `` | Переключить выборку перетаскивания | |
|
||||||
<kbd>a</kbd>: Переключить выборку частей
|
| `` a `` | Переключить выборку частей | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Скопировать выделенный текст в буфер обмена
|
| `` <c-o> `` | Скопировать выделенный текст в буфер обмена | |
|
||||||
<kbd>o</kbd>: Открыть файл
|
| `` <space> `` | Переключить индекс | Переключить строку в проиндексированные / непроиндексированные |
|
||||||
<kbd>e</kbd>: Редактировать файл
|
| `` d `` | Отменить изменение (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: Вернуться к панели файлов
|
| `` o `` | Открыть файл | Open file in default application. |
|
||||||
<kbd><tab></kbd>: Переключиться на другую панель (проиндексированные/непроиндексированные изменения)
|
| `` e `` | Редактировать файл | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Переключить строку в проиндексированные / непроиндексированные
|
| `` <esc> `` | Вернуться к панели файлов | |
|
||||||
<kbd>d</kbd>: Отменить изменение (git reset)
|
| `` <tab> `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Изменить эту часть
|
| `` E `` | Изменить эту часть | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: Сохранить изменения
|
| `` c `` | Сохранить изменения | Commit staged changes. |
|
||||||
<kbd>w</kbd>: Закоммитить изменения без предварительного хука коммита
|
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
|
||||||
<kbd>C</kbd>: Сохранить изменения с помощью редактора git
|
| `` C `` | Сохранить изменения с помощью редактора git | |
|
||||||
<kbd>/</kbd>: Найти
|
| `` / `` | Найти | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Главная панель (Обычный)
|
## Главная панель (Обычный)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: Прокрутить вниз (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: Прокрутить вверх (fn+down)
|
| `` mouse wheel down (fn+up) `` | Прокрутить вниз | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | Прокрутить вверх | |
|
||||||
|
|
||||||
## Главная панель (Слияние)
|
## Главная панель (Слияние)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: Редактировать файл
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: Открыть файл
|
| `` <space> `` | Выбрать эту часть | |
|
||||||
<kbd><left></kbd>: Выбрать предыдущий конфликт
|
| `` b `` | Выбрать все части | |
|
||||||
<kbd><right></kbd>: Выбрать следующий конфликт
|
| `` <up> `` | Выбрать предыдущую часть | |
|
||||||
<kbd><up></kbd>: Выбрать предыдущую часть
|
| `` <down> `` | Выбрать следующую часть | |
|
||||||
<kbd><down></kbd>: Выбрать следующую часть
|
| `` <left> `` | Выбрать предыдущий конфликт | |
|
||||||
<kbd>z</kbd>: Отменить
|
| `` <right> `` | Выбрать следующий конфликт | |
|
||||||
<kbd>M</kbd>: Открыть внешний инструмент слияния (git mergetool)
|
| `` z `` | Отменить | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: Выбрать эту часть
|
| `` e `` | Редактировать файл | Open file in external editor. |
|
||||||
<kbd>b</kbd>: Выбрать все части
|
| `` o `` | Открыть файл | Open file in default application. |
|
||||||
<kbd><esc></kbd>: Вернуться к панели файлов
|
| `` M `` | Открыть внешний инструмент слияния (git mergetool) | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | Вернуться к панели файлов | |
|
||||||
|
|
||||||
## Главная панель (сборка патчей)
|
## Главная панель (сборка патчей)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: Выбрать предыдущую часть
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: Выбрать следующую часть
|
| `` <left> `` | Выбрать предыдущую часть | |
|
||||||
<kbd>v</kbd>: Переключить выборку перетаскивания
|
| `` <right> `` | Выбрать следующую часть | |
|
||||||
<kbd>V</kbd>: Переключить выборку перетаскивания
|
| `` v `` | Переключить выборку перетаскивания | |
|
||||||
<kbd>a</kbd>: Переключить выборку частей
|
| `` a `` | Переключить выборку частей | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: Скопировать выделенный текст в буфер обмена
|
| `` <c-o> `` | Скопировать выделенный текст в буфер обмена | |
|
||||||
<kbd>o</kbd>: Открыть файл
|
| `` o `` | Открыть файл | Open file in default application. |
|
||||||
<kbd>e</kbd>: Редактировать файл
|
| `` e `` | Редактировать файл | Open file in external editor. |
|
||||||
<kbd><space></kbd>: Добавить/удалить строку(и) для патча
|
| `` <space> `` | Добавить/удалить строку(и) для патча | |
|
||||||
<kbd><esc></kbd>: Выйти из сборщика пользовательских патчей
|
| `` <esc> `` | Выйти из сборщика пользовательских патчей | |
|
||||||
<kbd>/</kbd>: Найти
|
| `` / `` | Найти | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Журнал ссылок (Reflog)
|
## Журнал ссылок (Reflog)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать SHA коммита в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Переключить коммит
|
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
|
||||||
<kbd>y</kbd>: Скопировать атрибут коммита
|
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Открыть коммит в браузере
|
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
| `` o `` | Открыть коммит в браузере | |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
| `` n `` | Создать новую ветку с этого коммита | |
|
||||||
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
|
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
|
| `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
| `` <c-r> `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | |
|
||||||
<kbd><enter></kbd>: Просмотреть коммиты
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Просмотреть коммиты | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Коммиты
|
## Коммиты
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать SHA коммита в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
|
||||||
<kbd>b</kbd>: Просмотреть параметры бинарного поиска
|
| `` <c-r> `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | |
|
||||||
<kbd>s</kbd>: Объединить несколько коммитов в один нижний
|
| `` b `` | Просмотреть параметры бинарного поиска | |
|
||||||
<kbd>f</kbd>: Объединить несколько коммитов в один отбросив сообщение коммита
|
| `` s `` | Объединить коммиты (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: Перефразировать коммит
|
| `` f `` | Объединить несколько коммитов в один отбросив сообщение коммита (Fixup) | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: Переписать коммит с помощью редактора
|
| `` r `` | Перефразировать коммит | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: Удалить коммит
|
| `` R `` | Переписать коммит с помощью редактора | |
|
||||||
<kbd>e</kbd>: Изменить коммит
|
| `` d `` | Удалить коммит | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: Выбрать коммит (в середине перебазирования)
|
| `` e `` | Edit (start interactive rebase) | Изменить коммит |
|
||||||
<kbd>F</kbd>: Создать fixup коммит для этого коммита
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: Переместить коммит вниз на один
|
| `` p `` | Pick | Выбрать коммит (в середине перебазирования) |
|
||||||
<kbd><c-k></kbd>: Переместить коммит вверх на один
|
| `` F `` | Create fixup commit | Создать fixup коммит для этого коммита |
|
||||||
<kbd>v</kbd>: Вставить отобранные коммиты (cherry-pick)
|
| `` S `` | Apply fixup commits | Объединить все 'fixup!' коммиты выше в выбранный коммит (автосохранение) |
|
||||||
<kbd>A</kbd>: Править последний коммит с проиндексированными изменениями
|
| `` <c-j> `` | Переместить коммит вниз на один | |
|
||||||
<kbd>a</kbd>: Установить/убрать автора коммита
|
| `` <c-k> `` | Переместить коммит вверх на один | |
|
||||||
<kbd>t</kbd>: Отменить коммит
|
| `` V `` | Вставить отобранные коммиты (cherry-pick) | |
|
||||||
<kbd>T</kbd>: Пометить коммит тегом
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: Открыть меню журнала
|
| `` A `` | Amend | Править последний коммит с проиндексированными изменениями |
|
||||||
<kbd><space></kbd>: Переключить коммит
|
| `` a `` | Установить/убрать автора коммита | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: Скопировать атрибут коммита
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: Открыть коммит в браузере
|
| `` T `` | Пометить коммит тегом | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
| `` <c-l> `` | Открыть меню журнала | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
|
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
|
| `` o `` | Открыть коммит в браузере | |
|
||||||
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
| `` n `` | Создать новую ветку с этого коммита | |
|
||||||
<kbd>/</kbd>: Найти
|
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | Просмотреть файлы выбранного элемента | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Найти | |
|
||||||
|
|
||||||
## Локальные Ветки
|
## Локальные Ветки
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать название ветки в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: Показать параметры git-flow
|
| `` <c-o> `` | Скопировать название ветки в буфер обмена | |
|
||||||
<kbd><space></kbd>: Переключить
|
| `` i `` | Показать параметры git-flow | |
|
||||||
<kbd>n</kbd>: Новая ветка
|
| `` <space> `` | Переключить | Checkout selected item. |
|
||||||
<kbd>o</kbd>: Создать запрос на принятие изменений
|
| `` n `` | Новая ветка | |
|
||||||
<kbd>O</kbd>: Создать параметры запроса принятие изменений
|
| `` o `` | Создать запрос на принятие изменений | |
|
||||||
<kbd><c-y></kbd>: Скопировать URL запроса на принятие изменений в буфер обмена
|
| `` O `` | Создать параметры запроса принятие изменений | |
|
||||||
<kbd>c</kbd>: Переключить по названию
|
| `` <c-y> `` | Скопировать URL запроса на принятие изменений в буфер обмена | |
|
||||||
<kbd>F</kbd>: Принудительное переключение
|
| `` c `` | Переключить по названию | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: Удалить ветку
|
| `` F `` | Принудительное переключение | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: Перебазировать переключённую ветку на эту ветку
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: Слияние с текущей переключённой веткой
|
| `` r `` | Перебазировать переключённую ветку на эту ветку | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: Перемотать эту ветку вперёд из её upstream-ветки
|
| `` M `` | Слияние с текущей переключённой веткой | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: Создать тег
|
| `` f `` | Перемотать эту ветку вперёд из её upstream-ветки | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
| `` T `` | Создать тег | |
|
||||||
<kbd>R</kbd>: Переименовать ветку
|
| `` s `` | Порядок сортировки | |
|
||||||
<kbd>u</kbd>: Установить/убрать upstream-ветку
|
| `` g `` | Просмотреть параметры сброса | |
|
||||||
<kbd><enter></kbd>: Просмотреть коммиты
|
| `` R `` | Переименовать ветку | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | Просмотреть коммиты | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Меню
|
## Меню
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Выполнить
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Закрыть
|
| `` <enter> `` | Выполнить | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | Закрыть | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Панель Подтверждения
|
## Панель Подтверждения
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Подтвердить
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Закрыть/отменить
|
| `` <enter> `` | Подтвердить | |
|
||||||
</pre>
|
| `` <esc> `` | Закрыть/отменить | |
|
||||||
|
|
||||||
## Подкоммиты
|
## Подкоммиты
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать SHA коммита в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Переключить коммит
|
| `` <c-o> `` | Скопировать SHA коммита в буфер обмена | |
|
||||||
<kbd>y</kbd>: Скопировать атрибут коммита
|
| `` <space> `` | Переключить | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: Открыть коммит в браузере
|
| `` y `` | Скопировать атрибут коммита | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: Создать новую ветку с этого коммита
|
| `` o `` | Открыть коммит в браузере | |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
| `` n `` | Создать новую ветку с этого коммита | |
|
||||||
<kbd>c</kbd>: Скопировать отобранные коммит (cherry-pick)
|
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: Скопировать несколько отобранных коммитов (cherry-pick)
|
| `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: Сбросить отобранную (скопированную | cherry-picked) выборку коммитов
|
| `` <c-r> `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | |
|
||||||
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Найти
|
| `` <enter> `` | Просмотреть файлы выбранного элемента | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Найти | |
|
||||||
|
|
||||||
## Подмодули
|
## Подмодули
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать название подмодуля в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: Ввести подмодуль
|
| `` <c-o> `` | Скопировать название подмодуля в буфер обмена | |
|
||||||
<kbd>d</kbd>: Удалить подмодуль
|
| `` <enter> `` | Enter | Ввести подмодуль |
|
||||||
<kbd>u</kbd>: Обновить подмодуль
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: Добавить новый подмодуль
|
| `` u `` | Update | Обновить подмодуль |
|
||||||
<kbd>e</kbd>: Обновить URL подмодуля
|
| `` n `` | Добавить новый подмодуль | |
|
||||||
<kbd>i</kbd>: Инициализировать подмодуль
|
| `` e `` | Обновить URL подмодуля | |
|
||||||
<kbd>b</kbd>: Просмотреть параметры массового подмодуля
|
| `` i `` | Initialize | Инициализировать подмодуль |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | Просмотреть параметры массового подмодуля | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Сводка коммита
|
## Сводка коммита
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: Подтвердить
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: Закрыть
|
| `` <enter> `` | Подтвердить | |
|
||||||
</pre>
|
| `` <esc> `` | Закрыть | |
|
||||||
|
|
||||||
## Сохранить Изменения Файлов
|
## Сохранить Изменения Файлов
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать закомиченное имя файла в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: Переключить файл
|
| `` <c-o> `` | Скопировать название файла в буфер обмена | |
|
||||||
<kbd>d</kbd>: Отменить изменения коммита в этом файле
|
| `` c `` | Переключить | Переключить файл |
|
||||||
<kbd>o</kbd>: Открыть файл
|
| `` d `` | Remove | Отменить изменения коммита в этом файле |
|
||||||
<kbd>e</kbd>: Редактировать файл
|
| `` o `` | Открыть файл | Open file in default application. |
|
||||||
<kbd><space></kbd>: Переключить файлы включённые в патч
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Переключить все файлы, включённые в патч
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: Введите файл, чтобы добавить выбранные строки в патч (или свернуть каталог переключения)
|
| `` <space> `` | Переключить файлы включённые в патч | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: Переключить вид дерева файлов
|
| `` a `` | Переключить все файлы, включённые в патч | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: Найти
|
| `` <enter> `` | Введите файл, чтобы добавить выбранные строки в патч (или свернуть каталог переключения) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | Переключить вид дерева файлов | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | Найти | |
|
||||||
|
|
||||||
## Статус
|
## Статус
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: Открыть файл конфигурации
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: Редактировать файл конфигурации
|
| `` o `` | Открыть файл конфигурации | Open file in default application. |
|
||||||
<kbd>u</kbd>: Проверить обновления
|
| `` e `` | Редактировать файл конфигурации | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: Переключиться на последний репозиторий
|
| `` u `` | Проверить обновления | |
|
||||||
<kbd>a</kbd>: Показать все логи ветки
|
| `` <enter> `` | Переключиться на последний репозиторий | |
|
||||||
</pre>
|
| `` a `` | Показать все логи ветки | |
|
||||||
|
|
||||||
## Теги
|
## Теги
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Переключить
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Удалить тег
|
| `` <space> `` | Переключить | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: Отправить тег
|
| `` n `` | Создать тег | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: Создать тег
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
| `` P `` | Отправить тег | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: Просмотреть коммиты
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Просмотреть коммиты | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Удалённые ветки
|
## Удалённые ветки
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать название ветки в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: Переключить
|
| `` <c-o> `` | Скопировать название ветки в буфер обмена | |
|
||||||
<kbd>n</kbd>: Новая ветка
|
| `` <space> `` | Переключить | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: Слияние с текущей переключённой веткой
|
| `` n `` | Новая ветка | |
|
||||||
<kbd>r</kbd>: Перебазировать переключённую ветку на эту ветку
|
| `` M `` | Слияние с текущей переключённой веткой | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: Удалить ветку
|
| `` r `` | Перебазировать переключённую ветку на эту ветку | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: Установить как upstream-ветку переключённую ветку
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса
|
| `` u `` | Set as upstream | Установить как upstream-ветку переключённую ветку |
|
||||||
<kbd><enter></kbd>: Просмотреть коммиты
|
| `` s `` | Порядок сортировки | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | Просмотреть коммиты | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Удалённые репозитории
|
## Удалённые репозитории
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: Получение изменения из удалённого репозитория
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: Добавить новую удалённую ветку
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: Удалить удалённую ветку
|
| `` n `` | Добавить новую удалённую ветку | |
|
||||||
<kbd>e</kbd>: Редактировать удалённый репозитории
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | Редактировать удалённый репозитории |
|
||||||
</pre>
|
| `` f `` | Получить изменения | Получение изменения из удалённого репозитория |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## Файлы
|
## Файлы
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: Скопировать название файла в буфер обмена
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: Просмотреть параметры «отмены изменении»
|
| `` <c-o> `` | Скопировать название файла в буфер обмена | |
|
||||||
<kbd><space></kbd>: Переключить индекс
|
| `` <space> `` | Переключить индекс | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: Фильтровать файлы (проиндексированные/непроиндексированные)
|
| `` <c-b> `` | Фильтровать файлы (проиндексированные/непроиндексированные) | |
|
||||||
<kbd>c</kbd>: Сохранить изменения
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: Закоммитить изменения без предварительного хука коммита
|
| `` c `` | Сохранить изменения | Commit staged changes. |
|
||||||
<kbd>A</kbd>: Правка последнего коммита
|
| `` w `` | Закоммитить изменения без предварительного хука коммита | |
|
||||||
<kbd>C</kbd>: Сохранить изменения с помощью редактора git
|
| `` A `` | Правка последнего коммита | |
|
||||||
<kbd>e</kbd>: Редактировать файл
|
| `` C `` | Сохранить изменения с помощью редактора git | |
|
||||||
<kbd>o</kbd>: Открыть файл
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: Игнорировать или исключить файл
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: Обновить файлы
|
| `` o `` | Открыть файл | Open file in default application. |
|
||||||
<kbd>s</kbd>: Припрятать все изменения
|
| `` i `` | Игнорировать или исключить файл | |
|
||||||
<kbd>S</kbd>: Просмотреть параметры хранилища
|
| `` r `` | Обновить файлы | |
|
||||||
<kbd>a</kbd>: Все проиндексированные/непроиндексированные
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: Проиндексировать отдельные части/строки для файла или свернуть/развернуть для каталога
|
| `` S `` | Просмотреть параметры хранилища | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: Просмотреть параметры сброса upstream-ветки
|
| `` a `` | Все проиндексированные/непроиндексированные | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: Просмотреть параметры сброса
|
| `` <enter> `` | Проиндексировать отдельные части/строки для файла или свернуть/развернуть для каталога | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: Переключить вид дерева файлов
|
| `` d `` | Просмотреть параметры «отмены изменении» | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: Открыть внешний инструмент слияния (git mergetool)
|
| `` g `` | Просмотреть параметры сброса upstream-ветки | |
|
||||||
<kbd>f</kbd>: Получить изменения
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: Найти
|
| `` ` `` | Переключить вид дерева файлов | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | Открыть внешний инструмент слияния (git mergetool) | Run `git mergetool`. |
|
||||||
|
| `` f `` | Получить изменения | Fetch changes from remote. |
|
||||||
|
| `` / `` | Найти | |
|
||||||
|
|
||||||
## Хранилище
|
## Хранилище
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: Применить припрятанные изменения
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: Применить припрятанные изменения и тут же удалить их из хранилища
|
| `` <space> `` | Применить припрятанные изменения | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: Удалить припрятанные изменения из хранилища
|
| `` g `` | Применить припрятанные изменения и тут же удалить их из хранилища | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: Новая ветка
|
| `` d `` | Удалить припрятанные изменения из хранилища | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Переименовать хранилище
|
| `` n `` | Новая ветка | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: Просмотреть файлы выбранного элемента
|
| `` r `` | Переименовать хранилище | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | Просмотреть файлы выбранного элемента | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit 按键绑定
|
# Lazygit 按键绑定
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _Legend: `<c-b>` means ctrl+b, `<a-b>` means alt+b, `B` means shift+b_
|
|||||||
|
|
||||||
## 全局键绑定
|
## 全局键绑定
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: 切换到最近的仓库
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: 向上滚动主面板 (fn+up/shift+k)
|
| `` <c-r> `` | 切换到最近的仓库 | |
|
||||||
<kbd><pgdown></kbd>: 向下滚动主面板 (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | 向上滚动主面板 | |
|
||||||
<kbd>@</kbd>: 打开命令日志菜单
|
| `` <pgdown> (fn+down/shift+j) `` | 向下滚动主面板 | |
|
||||||
<kbd>}</kbd>: 扩大差异视图中显示的上下文范围
|
| `` @ `` | 打开命令日志菜单 | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: 缩小差异视图中显示的上下文范围
|
| `` P `` | 推送 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: 执行自定义命令
|
| `` p `` | 拉取 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: 查看自定义补丁选项
|
| `` } `` | 扩大差异视图中显示的上下文范围 | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: 查看 合并/变基 选项
|
| `` { `` | 缩小差异视图中显示的上下文范围 | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: 刷新
|
| `` : `` | 执行自定义命令 | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: 下一屏模式(正常/半屏/全屏)
|
| `` <c-p> `` | 查看自定义补丁选项 | |
|
||||||
<kbd>_</kbd>: 上一屏模式
|
| `` m `` | 查看 合并/变基 选项 | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: 打开菜单
|
| `` R `` | 刷新 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: 查看按路径过滤选项
|
| `` + `` | 下一屏模式(正常/半屏/全屏) | |
|
||||||
<kbd>W</kbd>: 打开 diff 菜单
|
| `` _ `` | 上一屏模式 | |
|
||||||
<kbd><c-e></kbd>: 打开 diff 菜单
|
| `` ? `` | 打开菜单 | |
|
||||||
<kbd><c-w></kbd>: 切换是否在差异视图中显示空白字符差异
|
| `` <c-s> `` | 查看按路径过滤选项 | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: (通过 reflog)撤销「实验功能」
|
| `` W `` | 打开 diff 菜单 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: (通过 reflog)重做「实验功能」
|
| `` <c-e> `` | 打开 diff 菜单 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: 推送
|
| `` q `` | 退出 | |
|
||||||
<kbd>p</kbd>: 拉取
|
| `` <esc> `` | 取消 | |
|
||||||
</pre>
|
| `` <c-w> `` | 切换是否在差异视图中显示空白字符差异 | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | (通过 reflog)撤销「实验功能」 | The reflog will be used to determine what git command to run to undo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
| `` <c-z> `` | (通过 reflog)重做「实验功能」 | The reflog will be used to determine what git command to run to redo the last git command. This does not include changes to the working tree; only commits are taken into consideration. |
|
||||||
|
|
||||||
## 列表面板导航
|
## 列表面板导航
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: 上一页
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: 下一页
|
| `` , `` | 上一页 | |
|
||||||
<kbd><</kbd>: 滚动到顶部
|
| `` . `` | 下一页 | |
|
||||||
<kbd>></kbd>: 滚动到底部
|
| `` < `` | 滚动到顶部 | |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` > `` | 滚动到底部 | |
|
||||||
<kbd>H</kbd>: 向左滚动
|
| `` v `` | 切换拖动选择 | |
|
||||||
<kbd>L</kbd>: 向右滚动
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: 下一个标签
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: 上一个标签
|
| `` / `` | 开始搜索 | |
|
||||||
</pre>
|
| `` H `` | 向左滚动 | |
|
||||||
|
| `` L `` | 向右滚动 | |
|
||||||
|
| `` ] `` | 下一个标签 | |
|
||||||
|
| `` [ `` | 上一个标签 | |
|
||||||
|
|
||||||
## Reflog 页面
|
## Reflog 页面
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将提交的 SHA 复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 检出提交
|
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | 检出 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: 在浏览器中打开提交
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: 从提交创建新分支
|
| `` o `` | 在浏览器中打开提交 | |
|
||||||
<kbd>g</kbd>: 查看重置选项
|
| `` n `` | 从提交创建新分支 | |
|
||||||
<kbd>c</kbd>: 复制提交(拣选)
|
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: 复制提交范围(拣选)
|
| `` C `` | 复制提交(拣选) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
|
||||||
<kbd><enter></kbd>: 查看提交
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 查看提交 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 分支页面
|
## 分支页面
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将分支名称复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: 显示 git-flow 选项
|
| `` <c-o> `` | 将分支名称复制到剪贴板 | |
|
||||||
<kbd><space></kbd>: 检出
|
| `` i `` | 显示 git-flow 选项 | |
|
||||||
<kbd>n</kbd>: 新分支
|
| `` <space> `` | 检出 | Checkout selected item. |
|
||||||
<kbd>o</kbd>: 创建抓取请求
|
| `` n `` | 新分支 | |
|
||||||
<kbd>O</kbd>: 创建抓取请求选项
|
| `` o `` | 创建抓取请求 | |
|
||||||
<kbd><c-y></kbd>: 将抓取请求 URL 复制到剪贴板
|
| `` O `` | 创建抓取请求选项 | |
|
||||||
<kbd>c</kbd>: 按名称检出
|
| `` <c-y> `` | 将抓取请求 URL 复制到剪贴板 | |
|
||||||
<kbd>F</kbd>: 强制检出
|
| `` c `` | 按名称检出 | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: 删除分支
|
| `` F `` | 强制检出 | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: 将已检出的分支变基到该分支
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: 合并到当前检出的分支
|
| `` r `` | 将已检出的分支变基到该分支 | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: 从上游快进此分支
|
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: 创建标签
|
| `` f `` | 从上游快进此分支 | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: 查看重置选项
|
| `` T `` | 创建标签 | |
|
||||||
<kbd>R</kbd>: 重命名分支
|
| `` s `` | Sort order | |
|
||||||
<kbd>u</kbd>: Set/Unset upstream
|
| `` g `` | 查看重置选项 | |
|
||||||
<kbd><enter></kbd>: 查看提交
|
| `` R `` | 重命名分支 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | 查看提交 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 子提交
|
## 子提交
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将提交的 SHA 复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 检出提交
|
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` <space> `` | 检出 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: 在浏览器中打开提交
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: 从提交创建新分支
|
| `` o `` | 在浏览器中打开提交 | |
|
||||||
<kbd>g</kbd>: 查看重置选项
|
| `` n `` | 从提交创建新分支 | |
|
||||||
<kbd>c</kbd>: 复制提交(拣选)
|
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: 复制提交范围(拣选)
|
| `` C `` | 复制提交(拣选) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
|
||||||
<kbd><enter></kbd>: 查看提交的文件
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` <enter> `` | 查看提交的文件 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 开始搜索 | |
|
||||||
|
|
||||||
## 子模块
|
## 子模块
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将子模块名称复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: 输入子模块
|
| `` <c-o> `` | 将子模块名称复制到剪贴板 | |
|
||||||
<kbd>d</kbd>: 删除子模块
|
| `` <enter> `` | Enter | 输入子模块 |
|
||||||
<kbd>u</kbd>: 更新子模块
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: 添加新的子模块
|
| `` u `` | Update | 更新子模块 |
|
||||||
<kbd>e</kbd>: 更新子模块 URL
|
| `` n `` | 添加新的子模块 | |
|
||||||
<kbd>i</kbd>: 初始化子模块
|
| `` e `` | 更新子模块 URL | |
|
||||||
<kbd>b</kbd>: 查看批量子模块选项
|
| `` i `` | Initialize | 初始化子模块 |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | 查看批量子模块选项 | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 提交
|
## 提交
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将提交的 SHA 复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: 重置已拣选(复制)的提交
|
| `` <c-o> `` | 将提交的 SHA 复制到剪贴板 | |
|
||||||
<kbd>b</kbd>: 查看二分查找选项
|
| `` <c-r> `` | 重置已拣选(复制)的提交 | |
|
||||||
<kbd>s</kbd>: 向下压缩
|
| `` b `` | 查看二分查找选项 | |
|
||||||
<kbd>f</kbd>: 修正提交(fixup)
|
| `` s `` | 压缩 | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: 改写提交
|
| `` f `` | 修正(fixup) | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: 使用编辑器重命名提交
|
| `` r `` | 改写提交 | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: 删除提交
|
| `` R `` | 使用编辑器重命名提交 | |
|
||||||
<kbd>e</kbd>: 编辑提交
|
| `` d `` | 删除提交 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: 选择提交(变基过程中)
|
| `` e `` | Edit (start interactive rebase) | 编辑提交 |
|
||||||
<kbd>F</kbd>: 创建修正提交
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: 压缩在所选提交之上的所有“fixup!”提交(自动压缩)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: 下移提交
|
| `` p `` | Pick | 选择提交(变基过程中) |
|
||||||
<kbd><c-k></kbd>: 上移提交
|
| `` F `` | Create fixup commit | 创建修正提交 |
|
||||||
<kbd>v</kbd>: 粘贴提交(拣选)
|
| `` S `` | Apply fixup commits | 压缩在所选提交之上的所有“fixup!”提交(自动压缩) |
|
||||||
<kbd>A</kbd>: 用已暂存的更改来修补提交
|
| `` <c-j> `` | 下移提交 | |
|
||||||
<kbd>a</kbd>: Set/Reset commit author
|
| `` <c-k> `` | 上移提交 | |
|
||||||
<kbd>t</kbd>: 还原提交
|
| `` V `` | 粘贴提交(拣选) | |
|
||||||
<kbd>T</kbd>: 标签提交
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: 打开日志菜单
|
| `` A `` | Amend | 用已暂存的更改来修补提交 |
|
||||||
<kbd><space></kbd>: 检出提交
|
| `` a `` | Amend commit attribute | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: Copy commit attribute
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: 在浏览器中打开提交
|
| `` T `` | 标签提交 | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: 从提交创建新分支
|
| `` <c-l> `` | 打开日志菜单 | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: 查看重置选项
|
| `` <space> `` | 检出 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: 复制提交(拣选)
|
| `` y `` | Copy commit attribute to clipboard | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: 复制提交范围(拣选)
|
| `` o `` | 在浏览器中打开提交 | |
|
||||||
<kbd><enter></kbd>: 查看提交的文件
|
| `` n `` | 从提交创建新分支 | |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | 复制提交(拣选) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | 查看提交的文件 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 开始搜索 | |
|
||||||
|
|
||||||
## 提交文件
|
## 提交文件
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将提交的文件名复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: 检出文件
|
| `` <c-o> `` | 将文件名复制到剪贴板 | |
|
||||||
<kbd>d</kbd>: 放弃对此文件的提交更改
|
| `` c `` | 检出 | 检出文件 |
|
||||||
<kbd>o</kbd>: 打开文件
|
| `` d `` | Remove | 放弃对此文件的提交更改 |
|
||||||
<kbd>e</kbd>: 编辑文件
|
| `` o `` | 打开文件 | Open file in default application. |
|
||||||
<kbd><space></kbd>: 补丁中包含的切换文件
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: Toggle all files included in patch
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: 输入文件以将所选行添加到补丁中(或切换目录折叠)
|
| `` <space> `` | 补丁中包含的切换文件 | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: 切换文件树视图
|
| `` a `` | Toggle all files | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` <enter> `` | 输入文件以将所选行添加到补丁中(或切换目录折叠) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | 切换文件树视图 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | 开始搜索 | |
|
||||||
|
|
||||||
## 提交讯息
|
## 提交讯息
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 确认
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 关闭
|
| `` <enter> `` | 确认 | |
|
||||||
</pre>
|
| `` <esc> `` | 关闭 | |
|
||||||
|
|
||||||
## 文件
|
## 文件
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将文件名复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: 查看'放弃更改'选项
|
| `` <c-o> `` | 将文件名复制到剪贴板 | |
|
||||||
<kbd><space></kbd>: 切换暂存状态
|
| `` <space> `` | 切换暂存状态 | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: Filter files by status
|
| `` <c-b> `` | Filter files by status | |
|
||||||
<kbd>c</kbd>: 提交更改
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: 提交更改而无需预先提交钩子
|
| `` c `` | 提交更改 | Commit staged changes. |
|
||||||
<kbd>A</kbd>: 修补最后一次提交
|
| `` w `` | 提交更改而无需预先提交钩子 | |
|
||||||
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
|
| `` A `` | 修补最后一次提交 | |
|
||||||
<kbd>e</kbd>: 编辑文件
|
| `` C `` | 提交更改(使用编辑器编辑提交信息) | |
|
||||||
<kbd>o</kbd>: 打开文件
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: 忽略文件
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: 刷新文件
|
| `` o `` | 打开文件 | Open file in default application. |
|
||||||
<kbd>s</kbd>: 将所有更改加入贮藏
|
| `` i `` | 忽略文件 | |
|
||||||
<kbd>S</kbd>: 查看贮藏选项
|
| `` r `` | 刷新文件 | |
|
||||||
<kbd>a</kbd>: 切换所有文件的暂存状态
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: 暂存单个 块/行 用于文件, 或 折叠/展开 目录
|
| `` S `` | 查看贮藏选项 | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: 查看上游重置选项
|
| `` a `` | 切换所有文件的暂存状态 | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: 查看重置选项
|
| `` <enter> `` | 暂存单个 块/行 用于文件, 或 折叠/展开 目录 | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: 切换文件树视图
|
| `` d `` | 查看'放弃更改'选项 | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: 打开外部合并工具 (git mergetool)
|
| `` g `` | 查看上游重置选项 | |
|
||||||
<kbd>f</kbd>: 抓取
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` ` `` | 切换文件树视图 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | 打开外部合并工具 (git mergetool) | Run `git mergetool`. |
|
||||||
|
| `` f `` | 抓取 | Fetch changes from remote. |
|
||||||
|
| `` / `` | 开始搜索 | |
|
||||||
|
|
||||||
## 构建补丁中
|
## 构建补丁中
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 选择上一个区块
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 选择下一个区块
|
| `` <left> `` | 选择上一个区块 | |
|
||||||
<kbd>v</kbd>: 切换拖动选择
|
| `` <right> `` | 选择下一个区块 | |
|
||||||
<kbd>V</kbd>: 切换拖动选择
|
| `` v `` | 切换拖动选择 | |
|
||||||
<kbd>a</kbd>: 切换选择区块
|
| `` a `` | 切换选择区块 | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 将选中文本复制到剪贴板
|
| `` <c-o> `` | 将选中文本复制到剪贴板 | |
|
||||||
<kbd>o</kbd>: 打开文件
|
| `` o `` | 打开文件 | Open file in default application. |
|
||||||
<kbd>e</kbd>: 编辑文件
|
| `` e `` | 编辑文件 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 添加/移除 行到补丁
|
| `` <space> `` | 添加/移除 行到补丁 | |
|
||||||
<kbd><esc></kbd>: 退出逐行模式
|
| `` <esc> `` | 退出逐行模式 | |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` / `` | 开始搜索 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 标签页面
|
## 标签页面
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 检出
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: 删除标签
|
| `` <space> `` | 检出 | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: 推送标签
|
| `` n `` | 创建标签 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: 创建标签
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: 查看重置选项
|
| `` P `` | 推送标签 | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: 查看提交
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 查看提交 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 正在合并
|
## 正在合并
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: 编辑文件
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: 打开文件
|
| `` <space> `` | 选中区块 | |
|
||||||
<kbd><left></kbd>: 选择上一个冲突
|
| `` b `` | 选中所有区块 | |
|
||||||
<kbd><right></kbd>: 选择下一个冲突
|
| `` <up> `` | 选择顶部块 | |
|
||||||
<kbd><up></kbd>: 选择顶部块
|
| `` <down> `` | 选择底部块 | |
|
||||||
<kbd><down></kbd>: 选择底部块
|
| `` <left> `` | 选择上一个冲突 | |
|
||||||
<kbd>z</kbd>: 撤销
|
| `` <right> `` | 选择下一个冲突 | |
|
||||||
<kbd>M</kbd>: 打开外部合并工具 (git mergetool)
|
| `` z `` | 撤销 | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: 选中区块
|
| `` e `` | 编辑文件 | Open file in external editor. |
|
||||||
<kbd>b</kbd>: 选中所有区块
|
| `` o `` | 打开文件 | Open file in default application. |
|
||||||
<kbd><esc></kbd>: 返回文件面板
|
| `` M `` | 打开外部合并工具 (git mergetool) | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | 返回文件面板 | |
|
||||||
|
|
||||||
## 正在暂存
|
## 正在暂存
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 选择上一个区块
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 选择下一个区块
|
| `` <left> `` | 选择上一个区块 | |
|
||||||
<kbd>v</kbd>: 切换拖动选择
|
| `` <right> `` | 选择下一个区块 | |
|
||||||
<kbd>V</kbd>: 切换拖动选择
|
| `` v `` | 切换拖动选择 | |
|
||||||
<kbd>a</kbd>: 切换选择区块
|
| `` a `` | 切换选择区块 | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 将选中文本复制到剪贴板
|
| `` <c-o> `` | 将选中文本复制到剪贴板 | |
|
||||||
<kbd>o</kbd>: 打开文件
|
| `` <space> `` | 切换暂存状态 | 切换行暂存状态 |
|
||||||
<kbd>e</kbd>: 编辑文件
|
| `` d `` | 取消变更 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: 返回文件面板
|
| `` o `` | 打开文件 | Open file in default application. |
|
||||||
<kbd><tab></kbd>: 切换到其他面板
|
| `` e `` | 编辑文件 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 切换行暂存状态
|
| `` <esc> `` | 返回文件面板 | |
|
||||||
<kbd>d</kbd>: 取消变更 (git reset)
|
| `` <tab> `` | 切换到其他面板 | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: Edit hunk
|
| `` E `` | Edit hunk | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: 提交更改
|
| `` c `` | 提交更改 | Commit staged changes. |
|
||||||
<kbd>w</kbd>: 提交更改而无需预先提交钩子
|
| `` w `` | 提交更改而无需预先提交钩子 | |
|
||||||
<kbd>C</kbd>: 提交更改(使用编辑器编辑提交信息)
|
| `` C `` | 提交更改(使用编辑器编辑提交信息) | |
|
||||||
<kbd>/</kbd>: 开始搜索
|
| `` / `` | 开始搜索 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 正常
|
## 正常
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: 向下滚动 (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: 向上滚动 (fn+down)
|
| `` mouse wheel down (fn+up) `` | 向下滚动 | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | 向上滚动 | |
|
||||||
|
|
||||||
## 状态
|
## 状态
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: 打开配置文件
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: 编辑配置文件
|
| `` o `` | 打开配置文件 | Open file in default application. |
|
||||||
<kbd>u</kbd>: 检查更新
|
| `` e `` | 编辑配置文件 | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: 切换到最近的仓库
|
| `` u `` | 检查更新 | |
|
||||||
<kbd>a</kbd>: 显示所有分支的日志
|
| `` <enter> `` | 切换到最近的仓库 | |
|
||||||
</pre>
|
| `` a `` | 显示所有分支的日志 | |
|
||||||
|
|
||||||
## 确认面板
|
## 确认面板
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 确认
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 关闭
|
| `` <enter> `` | 确认 | |
|
||||||
</pre>
|
| `` <esc> `` | 关闭 | |
|
||||||
|
|
||||||
## 菜单
|
## 菜单
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 执行
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 关闭
|
| `` <enter> `` | 执行 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | 关闭 | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 贮藏
|
## 贮藏
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 应用
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: 应用并删除
|
| `` <space> `` | 应用 | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: 删除
|
| `` g `` | 应用并删除 | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: 新分支
|
| `` d `` | 删除 | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: Rename stash
|
| `` n `` | 新分支 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: 查看提交的文件
|
| `` r `` | Rename stash | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 查看提交的文件 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 远程分支
|
## 远程分支
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 将分支名称复制到剪贴板
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 检出
|
| `` <c-o> `` | 将分支名称复制到剪贴板 | |
|
||||||
<kbd>n</kbd>: 新分支
|
| `` <space> `` | 检出 | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: 合并到当前检出的分支
|
| `` n `` | 新分支 | |
|
||||||
<kbd>r</kbd>: 将已检出的分支变基到该分支
|
| `` M `` | 合并到当前检出的分支 | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: 删除分支
|
| `` r `` | 将已检出的分支变基到该分支 | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: 设置为检出分支的上游
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: 查看重置选项
|
| `` u `` | Set as upstream | 设置为检出分支的上游 |
|
||||||
<kbd><enter></kbd>: 查看提交
|
| `` s `` | Sort order | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | 查看重置选项 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | 查看提交 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 远程页面
|
## 远程页面
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: 抓取远程仓库
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: 添加新的远程仓库
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: 删除远程
|
| `` n `` | 添加新的远程仓库 | |
|
||||||
<kbd>e</kbd>: 编辑远程仓库
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | 编辑远程仓库 |
|
||||||
</pre>
|
| `` f `` | 抓取 | 抓取远程仓库 |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go run scripts/cheatsheet/main.go generate` from the project root._
|
_This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run `go generate ./...` from the project root._
|
||||||
|
|
||||||
# Lazygit 鍵盤快捷鍵
|
# Lazygit 鍵盤快捷鍵
|
||||||
|
|
||||||
@@ -6,328 +6,358 @@ _說明:`<c-b>` 表示 Ctrl+B、`<a-b>` 表示 Alt+B,`B`表示 Shift+B_
|
|||||||
|
|
||||||
## 全局快捷鍵
|
## 全局快捷鍵
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-r></kbd>: 切換到最近使用的版本庫
|
|-----|--------|-------------|
|
||||||
<kbd><pgup></kbd>: 向上捲動主面板 (fn+up/shift+k)
|
| `` <c-r> `` | 切換到最近使用的版本庫 | |
|
||||||
<kbd><pgdown></kbd>: 向下捲動主面板 (fn+down/shift+j)
|
| `` <pgup> (fn+up/shift+k) `` | 向上捲動主面板 | |
|
||||||
<kbd>@</kbd>: 開啟命令記錄選單
|
| `` <pgdown> (fn+down/shift+j) `` | 向下捲動主面板 | |
|
||||||
<kbd>}</kbd>: 增加差異檢視中顯示變更周圍上下文的大小
|
| `` @ `` | 開啟命令記錄選單 | View options for the command log e.g. show/hide the command log and focus the command log. |
|
||||||
<kbd>{</kbd>: 減小差異檢視中顯示變更周圍上下文的大小
|
| `` P `` | 推送 | Push the current branch to its upstream branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd>:</kbd>: 執行自訂命令
|
| `` p `` | 拉取 | Pull changes from the remote for the current branch. If no upstream is configured, you will be prompted to configure an upstream branch. |
|
||||||
<kbd><c-p></kbd>: 檢視自訂補丁選項
|
| `` } `` | 增加差異檢視中顯示變更周圍上下文的大小 | Increase the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>m</kbd>: 查看合併/變基選項
|
| `` { `` | 減小差異檢視中顯示變更周圍上下文的大小 | Decrease the amount of the context shown around changes in the diff view. |
|
||||||
<kbd>R</kbd>: 重新整理
|
| `` : `` | 執行自訂命令 | Bring up a prompt where you can enter a shell command to execute. Not to be confused with pre-configured custom commands. |
|
||||||
<kbd>+</kbd>: 下一個螢幕模式(常規/半螢幕/全螢幕)
|
| `` <c-p> `` | 檢視自訂補丁選項 | |
|
||||||
<kbd>_</kbd>: 上一個螢幕模式
|
| `` m `` | 查看合併/變基選項 | View options to abort/continue/skip the current merge/rebase. |
|
||||||
<kbd>?</kbd>: 開啟選單
|
| `` R `` | 重新整理 | Refresh the git state (i.e. run `git status`, `git branch`, etc in background to update the contents of panels). This does not run `git fetch`. |
|
||||||
<kbd><c-s></kbd>: 檢視篩選路徑選項
|
| `` + `` | 下一個螢幕模式(常規/半螢幕/全螢幕) | |
|
||||||
<kbd>W</kbd>: 開啟差異比較選單
|
| `` _ `` | 上一個螢幕模式 | |
|
||||||
<kbd><c-e></kbd>: 開啟差異比較選單
|
| `` ? `` | 開啟選單 | |
|
||||||
<kbd><c-w></kbd>: 切換是否在差異檢視中顯示空格變更
|
| `` <c-s> `` | 檢視篩選路徑選項 | View options for filtering the commit log by a file path, so that only commits relating to that path are shown. |
|
||||||
<kbd>z</kbd>: 復原
|
| `` W `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd><c-z></kbd>: 取消復原
|
| `` <c-e> `` | 開啟差異比較選單 | View options relating to diffing two refs e.g. diffing against selected ref, entering ref to diff against, and reversing the diff direction. |
|
||||||
<kbd>P</kbd>: 推送
|
| `` q `` | 結束 | |
|
||||||
<kbd>p</kbd>: 拉取
|
| `` <esc> `` | 取消 | |
|
||||||
</pre>
|
| `` <c-w> `` | 切換是否在差異檢視中顯示空格變更 | Toggle whether or not whitespace changes are shown in the diff view. |
|
||||||
|
| `` z `` | 復原 | 將使用 reflog 確定要運行哪個 git 命令以復原上一個 git 命令。這不包括工作區的更改;只考慮提交。 |
|
||||||
|
| `` <c-z> `` | 取消復原 | 將使用 reflog 確定要運行哪個 git 命令以重作上一個 git 命令。這不包括工作區的更改;只考慮提交。 |
|
||||||
|
|
||||||
## 列表面板導航
|
## 列表面板導航
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>,</kbd>: 上一頁
|
|-----|--------|-------------|
|
||||||
<kbd>.</kbd>: 下一頁
|
| `` , `` | 上一頁 | |
|
||||||
<kbd><</kbd>: 捲動到頂部
|
| `` . `` | 下一頁 | |
|
||||||
<kbd>></kbd>: 捲動到底部
|
| `` < `` | 捲動到頂部 | |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` > `` | 捲動到底部 | |
|
||||||
<kbd>H</kbd>: 向左捲動
|
| `` v `` | 切換拖曳選擇 | |
|
||||||
<kbd>L</kbd>: 向右捲動
|
| `` <s-down> `` | Range select down | |
|
||||||
<kbd>]</kbd>: 下一個索引標籤
|
| `` <s-up> `` | Range select up | |
|
||||||
<kbd>[</kbd>: 上一個索引標籤
|
| `` / `` | 開始搜尋 | |
|
||||||
</pre>
|
| `` H `` | 向左捲動 | |
|
||||||
|
| `` L `` | 向右捲動 | |
|
||||||
|
| `` ] `` | 下一個索引標籤 | |
|
||||||
|
| `` [ `` | 上一個索引標籤 | |
|
||||||
|
|
||||||
## Reflog
|
## Reflog
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製提交 SHA 到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 檢出提交
|
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
|
||||||
<kbd>y</kbd>: 複製提交屬性
|
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: 從提交建立新分支
|
| `` o `` | 在瀏覽器中開啟提交 | |
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
| `` n `` | 從提交建立新分支 | |
|
||||||
<kbd>c</kbd>: 複製提交 (揀選)
|
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: 複製提交範圍 (揀選)
|
| `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
|
||||||
<kbd><enter></kbd>: 檢視提交
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 檢視提交 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
|
## Worktrees
|
||||||
|
|
||||||
|
| Key | Action | Info |
|
||||||
|
|-----|--------|-------------|
|
||||||
|
| `` n `` | New worktree | |
|
||||||
|
| `` <space> `` | Switch | Switch to the selected worktree. |
|
||||||
|
| `` o `` | Open in editor | |
|
||||||
|
| `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 主視窗 (一般)
|
## 主視窗 (一般)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>mouse wheel down</kbd>: 向下捲動 (fn+up)
|
|-----|--------|-------------|
|
||||||
<kbd>mouse wheel up</kbd>: 向上捲動 (fn+down)
|
| `` mouse wheel down (fn+up) `` | 向下捲動 | |
|
||||||
</pre>
|
| `` mouse wheel up (fn+down) `` | 向上捲動 | |
|
||||||
|
|
||||||
## 主視窗 (合併中)
|
## 主視窗 (合併中)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>e</kbd>: 編輯檔案
|
|-----|--------|-------------|
|
||||||
<kbd>o</kbd>: 開啟檔案
|
| `` <space> `` | 挑選程式碼片段 | |
|
||||||
<kbd><left></kbd>: 選擇上一個衝突
|
| `` b `` | 挑選所有程式碼片段 | |
|
||||||
<kbd><right></kbd>: 選擇下一個衝突
|
| `` <up> `` | 選擇上一段 | |
|
||||||
<kbd><up></kbd>: 選擇上一段
|
| `` <down> `` | 選擇下一段 | |
|
||||||
<kbd><down></kbd>: 選擇下一段
|
| `` <left> `` | 選擇上一個衝突 | |
|
||||||
<kbd>z</kbd>: 復原
|
| `` <right> `` | 選擇下一個衝突 | |
|
||||||
<kbd>M</kbd>: 開啟外部合併工具 (git mergetool)
|
| `` z `` | 復原 | Undo last merge conflict resolution. |
|
||||||
<kbd><space></kbd>: 挑選程式碼片段
|
| `` e `` | 編輯檔案 | Open file in external editor. |
|
||||||
<kbd>b</kbd>: 挑選所有程式碼片段
|
| `` o `` | 開啟檔案 | Open file in default application. |
|
||||||
<kbd><esc></kbd>: 返回檔案面板
|
| `` M `` | 開啟外部合併工具 (git mergetool) | Run `git mergetool`. |
|
||||||
</pre>
|
| `` <esc> `` | 返回檔案面板 | |
|
||||||
|
|
||||||
## 主視窗 (預存中)
|
## 主視窗 (預存中)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 選擇上一段
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 選擇下一段
|
| `` <left> `` | 選擇上一段 | |
|
||||||
<kbd>v</kbd>: 切換拖曳選擇
|
| `` <right> `` | 選擇下一段 | |
|
||||||
<kbd>V</kbd>: 切換拖曳選擇
|
| `` v `` | 切換拖曳選擇 | |
|
||||||
<kbd>a</kbd>: 切換選擇程式碼塊
|
| `` a `` | 切換選擇程式碼塊 | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 複製所選文本至剪貼簿
|
| `` <c-o> `` | 複製所選文本至剪貼簿 | |
|
||||||
<kbd>o</kbd>: 開啟檔案
|
| `` <space> `` | 切換預存 | 切換現有行的狀態 (已預存/未預存) |
|
||||||
<kbd>e</kbd>: 編輯檔案
|
| `` d `` | 刪除變更 (git reset) | When unstaged change is selected, discard the change using `git reset`. When staged change is selected, unstage the change. |
|
||||||
<kbd><esc></kbd>: 返回檔案面板
|
| `` o `` | 開啟檔案 | Open file in default application. |
|
||||||
<kbd><tab></kbd>: 切換至另一個面板 (已預存/未預存更改)
|
| `` e `` | 編輯檔案 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 切換現有行的狀態 (已預存/未預存)
|
| `` <esc> `` | 返回檔案面板 | |
|
||||||
<kbd>d</kbd>: 刪除變更 (git reset)
|
| `` <tab> `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). |
|
||||||
<kbd>E</kbd>: 編輯程式碼塊
|
| `` E `` | 編輯程式碼塊 | Edit selected hunk in external editor. |
|
||||||
<kbd>c</kbd>: 提交變更
|
| `` c `` | 提交變更 | Commit staged changes. |
|
||||||
<kbd>w</kbd>: 沒有預提交 hook 就提交更改
|
| `` w `` | 沒有預提交 hook 就提交更改 | |
|
||||||
<kbd>C</kbd>: 使用 git 編輯器提交變更
|
| `` C `` | 使用 git 編輯器提交變更 | |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` / `` | 開始搜尋 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 主面板 (補丁生成)
|
## 主面板 (補丁生成)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><left></kbd>: 選擇上一段
|
|-----|--------|-------------|
|
||||||
<kbd><right></kbd>: 選擇下一段
|
| `` <left> `` | 選擇上一段 | |
|
||||||
<kbd>v</kbd>: 切換拖曳選擇
|
| `` <right> `` | 選擇下一段 | |
|
||||||
<kbd>V</kbd>: 切換拖曳選擇
|
| `` v `` | 切換拖曳選擇 | |
|
||||||
<kbd>a</kbd>: 切換選擇程式碼塊
|
| `` a `` | 切換選擇程式碼塊 | Toggle hunk selection mode. |
|
||||||
<kbd><c-o></kbd>: 複製所選文本至剪貼簿
|
| `` <c-o> `` | 複製所選文本至剪貼簿 | |
|
||||||
<kbd>o</kbd>: 開啟檔案
|
| `` o `` | 開啟檔案 | Open file in default application. |
|
||||||
<kbd>e</kbd>: 編輯檔案
|
| `` e `` | 編輯檔案 | Open file in external editor. |
|
||||||
<kbd><space></kbd>: 向 (或從) 補丁中添加/刪除行
|
| `` <space> `` | 向 (或從) 補丁中添加/刪除行 | |
|
||||||
<kbd><esc></kbd>: 退出自訂補丁建立器
|
| `` <esc> `` | 退出自訂補丁建立器 | |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` / `` | 開始搜尋 | |
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 功能表
|
## 功能表
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 執行
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 關閉
|
| `` <enter> `` | 執行 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <esc> `` | 關閉 | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 子提交
|
## 子提交
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製提交 SHA 到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 檢出提交
|
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
|
||||||
<kbd>y</kbd>: 複製提交屬性
|
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>n</kbd>: 從提交建立新分支
|
| `` o `` | 在瀏覽器中開啟提交 | |
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
| `` n `` | 從提交建立新分支 | |
|
||||||
<kbd>c</kbd>: 複製提交 (揀選)
|
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>C</kbd>: 複製提交範圍 (揀選)
|
| `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
|
||||||
<kbd><enter></kbd>: 檢視所選項目的檔案
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` <enter> `` | 檢視所選項目的檔案 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 開始搜尋 | |
|
||||||
|
|
||||||
## 子模組
|
## 子模組
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製子模組名稱到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd><enter></kbd>: 進入子模組
|
| `` <c-o> `` | 複製子模組名稱到剪貼簿 | |
|
||||||
<kbd>d</kbd>: 移除子模組
|
| `` <enter> `` | Enter | 進入子模組 |
|
||||||
<kbd>u</kbd>: 更新子模組
|
| `` d `` | Remove | Remove the selected submodule and its corresponding directory. |
|
||||||
<kbd>n</kbd>: 新增子模組
|
| `` u `` | Update | 更新子模組 |
|
||||||
<kbd>e</kbd>: 更新子模組 URL
|
| `` n `` | 新增子模組 | |
|
||||||
<kbd>i</kbd>: 初始化子模組
|
| `` e `` | 更新子模組 URL | |
|
||||||
<kbd>b</kbd>: 查看批量子模組選項
|
| `` i `` | Initialize | 初始化子模組 |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` b `` | 查看批量子模組選項 | |
|
||||||
</pre>
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 提交
|
## 提交
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製提交 SHA 到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd><c-r></kbd>: 重設選定的揀選 (複製) 提交
|
| `` <c-o> `` | 複製提交 SHA 到剪貼簿 | |
|
||||||
<kbd>b</kbd>: 查看二分選項
|
| `` <c-r> `` | 重設選定的揀選 (複製) 提交 | |
|
||||||
<kbd>s</kbd>: 向下壓縮
|
| `` b `` | 查看二分選項 | |
|
||||||
<kbd>f</kbd>: 修復提交 (Fixup)
|
| `` s `` | 壓縮 (Squash) | Squash the selected commit into the commit below it. The selected commit's message will be appended to the commit below it. |
|
||||||
<kbd>r</kbd>: 改寫提交
|
| `` f `` | 修復 (Fixup) | Meld the selected commit into the commit below it. Similar to fixup, but the selected commit's message will be discarded. |
|
||||||
<kbd>R</kbd>: 使用編輯器改寫提交
|
| `` r `` | 改寫提交 | Reword the selected commit's message. |
|
||||||
<kbd>d</kbd>: 刪除提交
|
| `` R `` | 使用編輯器改寫提交 | |
|
||||||
<kbd>e</kbd>: 編輯提交
|
| `` d `` | 刪除提交 | Drop the selected commit. This will remove the commit from the branch via a rebase. If the commit makes changes that later commits depend on, you may need to resolve merge conflicts. |
|
||||||
<kbd>p</kbd>: 挑選提交 (於變基過程中)
|
| `` e `` | Edit (start interactive rebase) | 編輯提交 |
|
||||||
<kbd>F</kbd>: 為此提交建立修復提交
|
| `` i `` | Start interactive rebase | Start an interactive rebase for the commits on your branch. This will include all commits from the HEAD commit down to the first merge commit or main branch commit.
|
||||||
<kbd>S</kbd>: 壓縮上方所有的“fixup!”提交 (自動壓縮)
|
If you would instead like to start an interactive rebase from the selected commit, press `e`. |
|
||||||
<kbd><c-j></kbd>: 向下移動提交
|
| `` p `` | Pick | 挑選提交 (於變基過程中) |
|
||||||
<kbd><c-k></kbd>: 向上移動提交
|
| `` F `` | Create fixup commit | 為此提交建立修復提交 |
|
||||||
<kbd>v</kbd>: 貼上提交 (揀選)
|
| `` S `` | Apply fixup commits | 壓縮上方所有的“fixup!”提交 (自動壓縮) |
|
||||||
<kbd>A</kbd>: 使用已預存的更改修正提交
|
| `` <c-j> `` | 向下移動提交 | |
|
||||||
<kbd>a</kbd>: 設置/重設提交作者
|
| `` <c-k> `` | 向上移動提交 | |
|
||||||
<kbd>t</kbd>: 還原提交
|
| `` V `` | 貼上提交 (揀選) | |
|
||||||
<kbd>T</kbd>: 打標籤到提交
|
| `` B `` | Mark as base commit for rebase | Select a base commit for the next rebase. When you rebase onto a branch, only commits above the base commit will be brought across. This uses the `git rebase --onto` command. |
|
||||||
<kbd><c-l></kbd>: 開啟記錄選單
|
| `` A `` | Amend | 使用已預存的更改修正提交 |
|
||||||
<kbd><space></kbd>: 檢出提交
|
| `` a `` | 設置/重設提交作者 | Set/Reset commit author or set co-author. |
|
||||||
<kbd>y</kbd>: 複製提交屬性
|
| `` t `` | Revert | Create a revert commit for the selected commit, which applies the selected commit's changes in reverse. |
|
||||||
<kbd>o</kbd>: 在瀏覽器中開啟提交
|
| `` T `` | 打標籤到提交 | Create a new tag pointing at the selected commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: 從提交建立新分支
|
| `` <c-l> `` | 開啟記錄選單 | View options for commit log e.g. changing sort order, hiding the git graph, showing the whole git graph. |
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
| `` <space> `` | 檢出 | Checkout the selected commit as a detached HEAD. |
|
||||||
<kbd>c</kbd>: 複製提交 (揀選)
|
| `` y `` | 複製提交屬性 | Copy commit attribute to clipboard (e.g. hash, URL, diff, message, author). |
|
||||||
<kbd>C</kbd>: 複製提交範圍 (揀選)
|
| `` o `` | 在瀏覽器中開啟提交 | |
|
||||||
<kbd><enter></kbd>: 檢視所選項目的檔案
|
| `` n `` | 從提交建立新分支 | |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `<esc>` to cancel the selection. |
|
||||||
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` <enter> `` | 檢視所選項目的檔案 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | 開始搜尋 | |
|
||||||
|
|
||||||
## 提交摘要
|
## 提交摘要
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 確認
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 關閉
|
| `` <enter> `` | 確認 | |
|
||||||
</pre>
|
| `` <esc> `` | 關閉 | |
|
||||||
|
|
||||||
## 提交檔案
|
## 提交檔案
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製提交的檔案名稱到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd>c</kbd>: 檢出檔案
|
| `` <c-o> `` | 複製檔案名稱到剪貼簿 | |
|
||||||
<kbd>d</kbd>: 捨棄此提交對此檔案的更改
|
| `` c `` | 檢出 | 檢出檔案 |
|
||||||
<kbd>o</kbd>: 開啟檔案
|
| `` d `` | Remove | 捨棄此提交對此檔案的更改 |
|
||||||
<kbd>e</kbd>: 編輯檔案
|
| `` o `` | 開啟檔案 | Open file in default application. |
|
||||||
<kbd><space></kbd>: 切換檔案是否包含在補丁中
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>a</kbd>: 切換所有檔案是否包含在補丁中
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
<kbd><enter></kbd>: 輸入檔案以將選定的行添加至補丁(或切換目錄折疊)
|
| `` <space> `` | 切換檔案是否包含在補丁中 | Toggle whether the file is included in the custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>`</kbd>: 切換檔案樹狀視圖
|
| `` a `` | 切換所有檔案是否包含在補丁中 | Add/remove all commit's files to custom patch. See https://github.com/jesseduffield/lazygit#rebase-magic-custom-patches. |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` <enter> `` | 輸入檔案以將選定的行添加至補丁(或切換目錄折疊) | If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory. |
|
||||||
</pre>
|
| `` ` `` | 切換檔案樹狀視圖 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
|
| `` / `` | 開始搜尋 | |
|
||||||
|
|
||||||
## 收藏 (Stash)
|
## 收藏 (Stash)
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 套用
|
|-----|--------|-------------|
|
||||||
<kbd>g</kbd>: 還原
|
| `` <space> `` | 套用 | Apply the stash entry to your working directory. |
|
||||||
<kbd>d</kbd>: 捨棄
|
| `` g `` | 還原 | Apply the stash entry to your working directory and remove the stash entry. |
|
||||||
<kbd>n</kbd>: 新分支
|
| `` d `` | 捨棄 | Remove the stash entry from the stash list. |
|
||||||
<kbd>r</kbd>: 重新命名收藏
|
| `` n `` | 新分支 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. |
|
||||||
<kbd><enter></kbd>: 檢視所選項目的檔案
|
| `` r `` | 重新命名收藏 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 檢視所選項目的檔案 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 本地分支
|
## 本地分支
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製分支名稱到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd>i</kbd>: 顯示 git-flow 選項
|
| `` <c-o> `` | 複製分支名稱到剪貼簿 | |
|
||||||
<kbd><space></kbd>: 檢出
|
| `` i `` | 顯示 git-flow 選項 | |
|
||||||
<kbd>n</kbd>: 新分支
|
| `` <space> `` | 檢出 | Checkout selected item. |
|
||||||
<kbd>o</kbd>: 建立拉取請求
|
| `` n `` | 新分支 | |
|
||||||
<kbd>O</kbd>: 建立拉取請求選項
|
| `` o `` | 建立拉取請求 | |
|
||||||
<kbd><c-y></kbd>: 複製拉取請求的 URL 到剪貼板
|
| `` O `` | 建立拉取請求選項 | |
|
||||||
<kbd>c</kbd>: 根據名稱檢出
|
| `` <c-y> `` | 複製拉取請求的 URL 到剪貼板 | |
|
||||||
<kbd>F</kbd>: 強制檢出
|
| `` c `` | 根據名稱檢出 | Checkout by name. In the input box you can enter '-' to switch to the last branch. |
|
||||||
<kbd>d</kbd>: 刪除分支
|
| `` F `` | 強制檢出 | Force checkout selected branch. This will discard all local changes in your working directory before checking out the selected branch. |
|
||||||
<kbd>r</kbd>: 將已檢出的分支變基至此分支
|
| `` d `` | Delete | View delete options for local/remote branch. |
|
||||||
<kbd>M</kbd>: 合併到當前檢出的分支
|
| `` r `` | 將已檢出的分支變基至此分支 | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>f</kbd>: 從上游快進此分支
|
| `` M `` | 合併到當前檢出的分支 | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>T</kbd>: 建立標籤
|
| `` f `` | 從上游快進此分支 | Fast-forward selected branch from its upstream. |
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
| `` T `` | 建立標籤 | |
|
||||||
<kbd>R</kbd>: 重新命名分支
|
| `` s `` | Sort order | |
|
||||||
<kbd>u</kbd>: 設定/取消設定上游
|
| `` g `` | 檢視重設選項 | |
|
||||||
<kbd><enter></kbd>: 檢視提交
|
| `` R `` | 重新命名分支 | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. |
|
||||||
</pre>
|
| `` <enter> `` | 檢視提交 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 標籤
|
## 標籤
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><space></kbd>: 檢出
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: 刪除標籤
|
| `` <space> `` | 檢出 | Checkout the selected tag tag as a detached HEAD. |
|
||||||
<kbd>P</kbd>: 推送標籤
|
| `` n `` | 建立標籤 | Create new tag from current commit. You'll be prompted to enter a tag name and optional description. |
|
||||||
<kbd>n</kbd>: 建立標籤
|
| `` d `` | Delete | View delete options for local/remote tag. |
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
| `` P `` | 推送標籤 | Push the selected tag to a remote. You'll be prompted to select a remote. |
|
||||||
<kbd><enter></kbd>: 檢視提交
|
| `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` <enter> `` | 檢視提交 | |
|
||||||
</pre>
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 檔案
|
## 檔案
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製檔案名稱到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd>d</kbd>: 檢視“捨棄更改”的選項
|
| `` <c-o> `` | 複製檔案名稱到剪貼簿 | |
|
||||||
<kbd><space></kbd>: 切換預存
|
| `` <space> `` | 切換預存 | Toggle staged for selected file. |
|
||||||
<kbd><c-b></kbd>: 篩選檔案 (預存/未預存)
|
| `` <c-b> `` | 篩選檔案 (預存/未預存) | |
|
||||||
<kbd>c</kbd>: 提交變更
|
| `` y `` | Copy to clipboard | |
|
||||||
<kbd>w</kbd>: 沒有預提交 hook 就提交更改
|
| `` c `` | 提交變更 | Commit staged changes. |
|
||||||
<kbd>A</kbd>: 修正上次提交
|
| `` w `` | 沒有預提交 hook 就提交更改 | |
|
||||||
<kbd>C</kbd>: 使用 git 編輯器提交變更
|
| `` A `` | 修正上次提交 | |
|
||||||
<kbd>e</kbd>: 編輯檔案
|
| `` C `` | 使用 git 編輯器提交變更 | |
|
||||||
<kbd>o</kbd>: 開啟檔案
|
| `` <c-f> `` | Find base commit for fixup | Find the commit that your current changes are building upon, for the sake of amending/fixing up the commit. This spares you from having to look through your branch's commits one-by-one to see which commit should be amended/fixed up. See docs: <https://github.com/jesseduffield/lazygit/tree/master/docs/Fixup_Commits.md> |
|
||||||
<kbd>i</kbd>: 忽略或排除檔案
|
| `` e `` | Edit | Open file in external editor. |
|
||||||
<kbd>r</kbd>: 重新整理檔案
|
| `` o `` | 開啟檔案 | Open file in default application. |
|
||||||
<kbd>s</kbd>: 收藏所有變更
|
| `` i `` | 忽略或排除檔案 | |
|
||||||
<kbd>S</kbd>: 檢視收藏選項
|
| `` r `` | 重新整理檔案 | |
|
||||||
<kbd>a</kbd>: 全部預存/取消預存
|
| `` s `` | Stash | Stash all changes. For other variations of stashing, use the view stash options keybinding. |
|
||||||
<kbd><enter></kbd>: 選擇檔案中的單個程式碼塊/行,或展開/折疊目錄
|
| `` S `` | 檢視收藏選項 | View stash options (e.g. stash all, stash staged, stash unstaged). |
|
||||||
<kbd>g</kbd>: 檢視上游重設選項
|
| `` a `` | 全部預存/取消預存 | Toggle staged/unstaged for all files in working tree. |
|
||||||
<kbd>D</kbd>: 檢視重設選項
|
| `` <enter> `` | 選擇檔案中的單個程式碼塊/行,或展開/折疊目錄 | If the selected item is a file, focus the staging view so you can stage individual hunks/lines. If the selected item is a directory, collapse/expand it. |
|
||||||
<kbd>`</kbd>: 切換檔案樹狀視圖
|
| `` d `` | 檢視“捨棄更改”的選項 | View options for discarding changes to the selected file. |
|
||||||
<kbd>M</kbd>: 開啟外部合併工具 (git mergetool)
|
| `` g `` | 檢視上游重設選項 | |
|
||||||
<kbd>f</kbd>: 擷取
|
| `` D `` | Reset | View reset options for working tree (e.g. nuking the working tree). |
|
||||||
<kbd>/</kbd>: 開始搜尋
|
| `` ` `` | 切換檔案樹狀視圖 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. |
|
||||||
</pre>
|
| `` <c-t> `` | Open external diff tool (git difftool) | |
|
||||||
|
| `` M `` | 開啟外部合併工具 (git mergetool) | Run `git mergetool`. |
|
||||||
|
| `` f `` | 擷取 | Fetch changes from remote. |
|
||||||
|
| `` / `` | 開始搜尋 | |
|
||||||
|
|
||||||
## 狀態
|
## 狀態
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>o</kbd>: 開啟設定檔案
|
|-----|--------|-------------|
|
||||||
<kbd>e</kbd>: 編輯設定檔案
|
| `` o `` | 開啟設定檔案 | Open file in default application. |
|
||||||
<kbd>u</kbd>: 檢查更新
|
| `` e `` | 編輯設定檔案 | Open file in external editor. |
|
||||||
<kbd><enter></kbd>: 切換到最近使用的版本庫
|
| `` u `` | 檢查更新 | |
|
||||||
<kbd>a</kbd>: 顯示所有分支日誌
|
| `` <enter> `` | 切換到最近使用的版本庫 | |
|
||||||
</pre>
|
| `` a `` | 顯示所有分支日誌 | |
|
||||||
|
|
||||||
## 確認面板
|
## 確認面板
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><enter></kbd>: 確認
|
|-----|--------|-------------|
|
||||||
<kbd><esc></kbd>: 關閉/取消
|
| `` <enter> `` | 確認 | |
|
||||||
</pre>
|
| `` <esc> `` | 關閉/取消 | |
|
||||||
|
|
||||||
## 遠端
|
## 遠端
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd>f</kbd>: 擷取遠端
|
|-----|--------|-------------|
|
||||||
<kbd>n</kbd>: 新增遠端
|
| `` <enter> `` | View branches | |
|
||||||
<kbd>d</kbd>: 移除遠端
|
| `` n `` | 新增遠端 | |
|
||||||
<kbd>e</kbd>: 編輯遠端
|
| `` d `` | Remove | Remove the selected remote. Any local branches tracking a remote branch from the remote will be unaffected. |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` e `` | Edit | 編輯遠端 |
|
||||||
</pre>
|
| `` f `` | 擷取 | 擷取遠端 |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|
||||||
## 遠端分支
|
## 遠端分支
|
||||||
|
|
||||||
<pre>
|
| Key | Action | Info |
|
||||||
<kbd><c-o></kbd>: 複製分支名稱到剪貼簿
|
|-----|--------|-------------|
|
||||||
<kbd><space></kbd>: 檢出
|
| `` <c-o> `` | 複製分支名稱到剪貼簿 | |
|
||||||
<kbd>n</kbd>: 新分支
|
| `` <space> `` | 檢出 | Checkout a new local branch based on the selected remote branch. The new branch will track the remote branch. |
|
||||||
<kbd>M</kbd>: 合併到當前檢出的分支
|
| `` n `` | 新分支 | |
|
||||||
<kbd>r</kbd>: 將已檢出的分支變基至此分支
|
| `` M `` | 合併到當前檢出的分支 | Merge selected branch into currently checked out branch. |
|
||||||
<kbd>d</kbd>: 刪除分支
|
| `` r `` | 將已檢出的分支變基至此分支 | Rebase the checked-out branch onto the selected branch. |
|
||||||
<kbd>u</kbd>: 將此分支設為當前分支之上游
|
| `` d `` | Delete | Delete the remote branch from the remote. |
|
||||||
<kbd>g</kbd>: 檢視重設選項
|
| `` u `` | Set as upstream | 將此分支設為當前分支之上游 |
|
||||||
<kbd><enter></kbd>: 檢視提交
|
| `` s `` | Sort order | |
|
||||||
<kbd>/</kbd>: Filter the current view by text
|
| `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. |
|
||||||
</pre>
|
| `` <enter> `` | 檢視提交 | |
|
||||||
|
| `` w `` | View worktree options | |
|
||||||
|
| `` / `` | Filter the current view by text | |
|
||||||
|
|||||||
@@ -1,46 +1,50 @@
|
|||||||
module github.com/jesseduffield/lazygit
|
module github.com/jesseduffield/lazygit
|
||||||
|
|
||||||
go 1.18
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/OpenPeeDeeP/xdg v1.0.0
|
github.com/OpenPeeDeeP/xdg v1.0.0
|
||||||
github.com/atotto/clipboard v0.1.4
|
github.com/atotto/clipboard v0.1.4
|
||||||
github.com/aybabtme/humanlog v0.4.1
|
github.com/aybabtme/humanlog v0.4.1
|
||||||
github.com/cli/safeexec v1.0.0
|
|
||||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
|
||||||
github.com/creack/pty v1.1.11
|
github.com/creack/pty v1.1.11
|
||||||
github.com/fsmiamoto/git-todo-parser v0.0.5
|
github.com/fsmiamoto/git-todo-parser v0.0.5
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/gdamore/tcell/v2 v2.7.1-0.20240121011954-0393f5eb0b1a
|
||||||
github.com/gdamore/tcell/v2 v2.6.0
|
github.com/go-errors/errors v1.5.1
|
||||||
github.com/go-errors/errors v1.4.2
|
|
||||||
github.com/gookit/color v1.4.2
|
github.com/gookit/color v1.4.2
|
||||||
github.com/imdario/mergo v0.3.11
|
github.com/imdario/mergo v0.3.11
|
||||||
github.com/integrii/flaggy v1.4.0
|
github.com/integrii/flaggy v1.4.0
|
||||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b
|
github.com/jesseduffield/gocui v0.3.1-0.20240129213945-26fc8669eb5b
|
||||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
||||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
||||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
||||||
|
github.com/jesseduffield/yaml v2.1.0+incompatible
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
|
||||||
|
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3
|
||||||
github.com/kyokomi/emoji/v2 v2.2.8
|
github.com/kyokomi/emoji/v2 v2.2.8
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||||
github.com/mattn/go-runewidth v0.0.14
|
github.com/mattn/go-runewidth v0.0.15
|
||||||
github.com/mgutz/str v1.2.0
|
github.com/mgutz/str v1.2.0
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
github.com/mitchellh/go-ps v1.0.0
|
||||||
github.com/sahilm/fuzzy v0.1.0
|
github.com/sahilm/fuzzy v0.1.0
|
||||||
github.com/samber/lo v1.31.0
|
github.com/samber/lo v1.31.0
|
||||||
github.com/sanity-io/litter v1.5.2
|
github.com/sanity-io/litter v1.5.2
|
||||||
github.com/sasha-s/go-deadlock v0.3.1
|
github.com/sasha-s/go-deadlock v0.3.1
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
github.com/spf13/afero v1.9.5
|
||||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778
|
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778
|
||||||
|
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8
|
||||||
gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0
|
gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||||
|
github.com/buger/jsonparser v1.1.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/emirpasic/gods v1.12.0 // indirect
|
github.com/emirpasic/gods v1.12.0 // indirect
|
||||||
github.com/fatih/color v1.9.0 // indirect
|
github.com/fatih/color v1.9.0 // indirect
|
||||||
@@ -50,25 +54,28 @@ require (
|
|||||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||||
github.com/gobwas/glob v0.2.3 // indirect
|
github.com/gobwas/glob v0.2.3 // indirect
|
||||||
github.com/google/go-cmp v0.5.6 // indirect
|
github.com/google/go-cmp v0.5.6 // indirect
|
||||||
|
github.com/invopop/jsonschema v0.10.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.11 // indirect
|
github.com/mattn/go-colorable v0.1.11 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/onsi/ginkgo v1.10.3 // indirect
|
github.com/onsi/ginkgo v1.10.3 // indirect
|
||||||
github.com/onsi/gomega v1.7.1 // indirect
|
github.com/onsi/gomega v1.7.1 // indirect
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.6 // indirect
|
||||||
github.com/sergi/go-diff v1.1.0 // indirect
|
github.com/sergi/go-diff v1.1.0 // indirect
|
||||||
|
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||||
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 // indirect
|
|
||||||
golang.org/x/net v0.7.0 // indirect
|
golang.org/x/net v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.10.0 // indirect
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
golang.org/x/term v0.10.0 // indirect
|
golang.org/x/term v0.16.0 // indirect
|
||||||
golang.org/x/text v0.11.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,43 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||||
|
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||||
|
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
|
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/OpenPeeDeeP/xdg v1.0.0 h1:UDLmNjCGFZZCaVMB74DqYEtXkHxnTxcr4FeJVF9uCn8=
|
github.com/OpenPeeDeeP/xdg v1.0.0 h1:UDLmNjCGFZZCaVMB74DqYEtXkHxnTxcr4FeJVF9uCn8=
|
||||||
github.com/OpenPeeDeeP/xdg v1.0.0/go.mod h1:tMoSueLQlMf0TCldjrJLNIjAc5qAOIcHt5REi88/Ygo=
|
github.com/OpenPeeDeeP/xdg v1.0.0/go.mod h1:tMoSueLQlMf0TCldjrJLNIjAc5qAOIcHt5REi88/Ygo=
|
||||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||||
@@ -11,10 +51,20 @@ github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn
|
|||||||
github.com/aybabtme/humanlog v0.4.1 h1:D8d9um55rrthJsP8IGSHBcti9lTb/XknmDAX6Zy8tek=
|
github.com/aybabtme/humanlog v0.4.1 h1:D8d9um55rrthJsP8IGSHBcti9lTb/XknmDAX6Zy8tek=
|
||||||
github.com/aybabtme/humanlog v0.4.1/go.mod h1:B0bnQX4FTSU3oftPMTTPvENCy8LqixLDvYJA9TUCAGo=
|
github.com/aybabtme/humanlog v0.4.1/go.mod h1:B0bnQX4FTSU3oftPMTTPvENCy8LqixLDvYJA9TUCAGo=
|
||||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||||
github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
|
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||||
github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
|
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||||
|
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||||
|
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
|
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
|
||||||
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
|
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
@@ -24,70 +74,145 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.1-0.20180516100307-2d684516a886/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
github.com/fsmiamoto/git-todo-parser v0.0.5 h1:Bhzd/vz/6Qm3udfkd6NO9fWfD3TpwR9ucp3N75/J5I8=
|
github.com/fsmiamoto/git-todo-parser v0.0.5 h1:Bhzd/vz/6Qm3udfkd6NO9fWfD3TpwR9ucp3N75/J5I8=
|
||||||
github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas=
|
github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLIaEWvwr2sxKYYb0Fas=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU=
|
github.com/gdamore/tcell/v2 v2.7.1-0.20240103180601-96e29905643b/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8=
|
||||||
github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg=
|
github.com/gdamore/tcell/v2 v2.7.1-0.20240121011954-0393f5eb0b1a h1:IgatwqPZL0RPblLezzibmx8GgARDjOQOvrLpCWLmZak=
|
||||||
github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y=
|
github.com/gdamore/tcell/v2 v2.7.1-0.20240121011954-0393f5eb0b1a/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8=
|
||||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
||||||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
|
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||||
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
|
github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
|
||||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/integrii/flaggy v1.4.0 h1:A1x7SYx4jqu5NSrY14z8Z+0UyX2S5ygfJJrfolWR3zM=
|
github.com/integrii/flaggy v1.4.0 h1:A1x7SYx4jqu5NSrY14z8Z+0UyX2S5ygfJJrfolWR3zM=
|
||||||
github.com/integrii/flaggy v1.4.0/go.mod h1:tnTxHeTJbah0gQ6/K0RW0J7fMUBk9MCF5blhm43LNpI=
|
github.com/integrii/flaggy v1.4.0/go.mod h1:tnTxHeTJbah0gQ6/K0RW0J7fMUBk9MCF5blhm43LNpI=
|
||||||
|
github.com/invopop/jsonschema v0.10.0 h1:c1ktzNLBun3LyQQhyty5WE3lulbOdIIyOVlkmDLehcE=
|
||||||
|
github.com/invopop/jsonschema v0.10.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8TIcC6Y4RI+1ZbJDOHfGJ570tPeYVCqo7/tws=
|
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8TIcC6Y4RI+1ZbJDOHfGJ570tPeYVCqo7/tws=
|
||||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
||||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
||||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b h1:8FmmdaYHes1m3oNyNdS+VIgkgkFpNZAWuwTnvp0tG14=
|
github.com/jesseduffield/gocui v0.3.1-0.20240129213945-26fc8669eb5b h1:QASuIUc76BuFmSuzzqwzjpsn23r8ybfDqbKsY2WzTrE=
|
||||||
github.com/jesseduffield/gocui v0.3.1-0.20230710004407-9bbfd873713b/go.mod h1:dJ/BEUt3OWtaRg/PmuJWendRqREhre9JQ1SLvqrVJ8s=
|
github.com/jesseduffield/gocui v0.3.1-0.20240129213945-26fc8669eb5b/go.mod h1:9zkyjnUmdL3+sUknJrQy/3HweUu8mVln/3J2wRF/l8M=
|
||||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
||||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
||||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
||||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
|
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
|
||||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U=
|
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U=
|
||||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e/go.mod h1:u60qdFGXRd36jyEXxetz0vQceQIxzI13lIo3EFUDf4I=
|
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e/go.mod h1:u60qdFGXRd36jyEXxetz0vQceQIxzI13lIo3EFUDf4I=
|
||||||
|
github.com/jesseduffield/yaml v2.1.0+incompatible h1:HWQJ1gIv2zHKbDYNp0Jwjlj24K8aqpFHnMCynY1EpmE=
|
||||||
|
github.com/jesseduffield/yaml v2.1.0+incompatible/go.mod h1:w0xGhOSIJCGYYW+hnFPTutCy5aACpkcwbmORt5axGqk=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||||
|
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3 h1:s995u+gNQADMaixtNOs+jilRC/Q78q0UXSI7+4T0cDE=
|
||||||
|
github.com/karimkhaleel/jsonschema v0.0.0-20231001195015-d933f0d94ea3/go.mod h1:MCbEh21gjOzxc31udr3u4QM9DAdf8TFJCZz3u5hYIxA=
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
@@ -99,9 +224,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
|
|||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
|
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
|
||||||
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
||||||
@@ -111,13 +237,14 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
|
||||||
github.com/mgutz/str v1.2.0 h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=
|
github.com/mgutz/str v1.2.0 h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=
|
||||||
github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w=
|
github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||||
|
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
@@ -127,16 +254,19 @@ github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
|||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg=
|
||||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
||||||
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
github.com/samber/lo v1.31.0 h1:Sfa+/064Tdo4SvlohQUQzBhgSer9v/coGvKQI/XLWAM=
|
github.com/samber/lo v1.31.0 h1:Sfa+/064Tdo4SvlohQUQzBhgSer9v/coGvKQI/XLWAM=
|
||||||
@@ -149,88 +279,367 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
|||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||||
|
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
|
||||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc=
|
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc=
|
||||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
|
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
|
||||||
github.com/urfave/cli v1.20.1-0.20180226030253-8e01ec4cd3e2/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.1-0.20180226030253-8e01ec4cd3e2/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||||
|
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||||
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
|
||||||
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 h1:s/+U+w0teGzcoH2mdIlFQ6KfVKGaYpgyGdUefZrn9TU=
|
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 h1:s/+U+w0teGzcoH2mdIlFQ6KfVKGaYpgyGdUefZrn9TU=
|
||||||
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20170407050850-f3918c30c5c2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20170407050850-f3918c30c5c2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||||
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
|
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
|
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
|
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||||
|
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0 h1:KzcWKJ0nMAmGoBhYVMnkWc1rXjB42lKy5aIys4TdLOA=
|
gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0 h1:KzcWKJ0nMAmGoBhYVMnkWc1rXjB42lKy5aIys4TdLOA=
|
||||||
@@ -246,3 +655,13 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|||||||
+15
-7
@@ -11,8 +11,8 @@ import (
|
|||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
|
appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/env"
|
"github.com/jesseduffield/lazygit/pkg/env"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui"
|
"github.com/jesseduffield/lazygit/pkg/gui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||||
|
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/logs"
|
"github.com/jesseduffield/lazygit/pkg/logs"
|
||||||
"github.com/jesseduffield/lazygit/pkg/updates"
|
"github.com/jesseduffield/lazygit/pkg/updates"
|
||||||
)
|
)
|
||||||
@@ -42,7 +43,7 @@ func Run(
|
|||||||
common *common.Common,
|
common *common.Common,
|
||||||
startArgs appTypes.StartArgs,
|
startArgs appTypes.StartArgs,
|
||||||
) {
|
) {
|
||||||
app, err := NewApp(config, common)
|
app, err := NewApp(config, startArgs.IntegrationTest, common)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = app.Run(startArgs)
|
err = app.Run(startArgs)
|
||||||
@@ -62,6 +63,7 @@ func Run(
|
|||||||
|
|
||||||
func NewCommon(config config.AppConfigurer) (*common.Common, error) {
|
func NewCommon(config config.AppConfigurer) (*common.Common, error) {
|
||||||
userConfig := config.GetUserConfig()
|
userConfig := config.GetUserConfig()
|
||||||
|
appState := config.GetAppState()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
log := newLogger(config)
|
log := newLogger(config)
|
||||||
@@ -74,7 +76,9 @@ func NewCommon(config config.AppConfigurer) (*common.Common, error) {
|
|||||||
Log: log,
|
Log: log,
|
||||||
Tr: tr,
|
Tr: tr,
|
||||||
UserConfig: userConfig,
|
UserConfig: userConfig,
|
||||||
|
AppState: appState,
|
||||||
Debug: config.GetDebug(),
|
Debug: config.GetDebug(),
|
||||||
|
Fs: afero.NewOsFs(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +95,7 @@ func newLogger(cfg config.AppConfigurer) *logrus.Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewApp bootstrap a new application
|
// NewApp bootstrap a new application
|
||||||
func NewApp(config config.AppConfigurer, common *common.Common) (*App, error) {
|
func NewApp(config config.AppConfigurer, test integrationTypes.IntegrationTest, common *common.Common) (*App, error) {
|
||||||
app := &App{
|
app := &App{
|
||||||
closers: []io.Closer{},
|
closers: []io.Closer{},
|
||||||
Config: config,
|
Config: config,
|
||||||
@@ -125,7 +129,7 @@ func NewApp(config config.AppConfigurer, common *common.Common) (*App, error) {
|
|||||||
showRecentRepos = true
|
showRecentRepos = true
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Gui, err = gui.NewGui(common, config, gitVersion, updater, showRecentRepos, dirName)
|
app.Gui, err = gui.NewGui(common, config, gitVersion, updater, showRecentRepos, dirName, test)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return app, err
|
return app, err
|
||||||
}
|
}
|
||||||
@@ -265,7 +269,11 @@ func (app *App) Run(startArgs appTypes.StartArgs) error {
|
|||||||
|
|
||||||
// Close closes any resources
|
// Close closes any resources
|
||||||
func (app *App) Close() error {
|
func (app *App) Close() error {
|
||||||
return slices.TryForEach(app.closers, func(closer io.Closer) error {
|
for _, closer := range app.closers {
|
||||||
return closer.Close()
|
if err := closer.Close(); err != nil {
|
||||||
})
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-31
@@ -5,12 +5,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/secureexec"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
@@ -34,8 +34,8 @@ const (
|
|||||||
|
|
||||||
DaemonKindExitImmediately
|
DaemonKindExitImmediately
|
||||||
DaemonKindCherryPick
|
DaemonKindCherryPick
|
||||||
DaemonKindMoveTodoUp
|
DaemonKindMoveTodosUp
|
||||||
DaemonKindMoveTodoDown
|
DaemonKindMoveTodosDown
|
||||||
DaemonKindInsertBreak
|
DaemonKindInsertBreak
|
||||||
DaemonKindChangeTodoActions
|
DaemonKindChangeTodoActions
|
||||||
DaemonKindMoveFixupCommitDown
|
DaemonKindMoveFixupCommitDown
|
||||||
@@ -56,8 +56,8 @@ func getInstruction() Instruction {
|
|||||||
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
|
DaemonKindCherryPick: deserializeInstruction[*CherryPickCommitsInstruction],
|
||||||
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
|
DaemonKindChangeTodoActions: deserializeInstruction[*ChangeTodoActionsInstruction],
|
||||||
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
|
DaemonKindMoveFixupCommitDown: deserializeInstruction[*MoveFixupCommitDownInstruction],
|
||||||
DaemonKindMoveTodoUp: deserializeInstruction[*MoveTodoUpInstruction],
|
DaemonKindMoveTodosUp: deserializeInstruction[*MoveTodosUpInstruction],
|
||||||
DaemonKindMoveTodoDown: deserializeInstruction[*MoveTodoDownInstruction],
|
DaemonKindMoveTodosDown: deserializeInstruction[*MoveTodosDownInstruction],
|
||||||
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
DaemonKindInsertBreak: deserializeInstruction[*InsertBreakInstruction],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ func getDaemonKind() DaemonKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getCommentChar() byte {
|
func getCommentChar() byte {
|
||||||
cmd := secureexec.Command("git", "config", "--get", "--null", "core.commentChar")
|
cmd := exec.Command("git", "config", "--get", "--null", "core.commentChar")
|
||||||
if output, err := cmd.Output(); err == nil && len(output) == 2 {
|
if output, err := cmd.Output(); err == nil && len(output) == 2 {
|
||||||
return output[0]
|
return output[0]
|
||||||
}
|
}
|
||||||
@@ -208,13 +208,15 @@ func (self *ChangeTodoActionsInstruction) SerializedInstructions() string {
|
|||||||
|
|
||||||
func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
|
func (self *ChangeTodoActionsInstruction) run(common *common.Common) error {
|
||||||
return handleInteractiveRebase(common, func(path string) error {
|
return handleInteractiveRebase(common, func(path string) error {
|
||||||
for _, c := range self.Changes {
|
changes := lo.Map(self.Changes, func(c ChangeTodoAction, _ int) utils.TodoChange {
|
||||||
if err := utils.EditRebaseTodo(path, c.Sha, todo.Pick, c.NewAction, getCommentChar()); err != nil {
|
return utils.TodoChange{
|
||||||
return err
|
Sha: c.Sha,
|
||||||
|
OldAction: todo.Pick,
|
||||||
|
NewAction: c.NewAction,
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
return nil
|
return utils.EditRebaseTodo(path, changes, getCommentChar())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,51 +249,65 @@ func (self *MoveFixupCommitDownInstruction) run(common *common.Common) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type MoveTodoUpInstruction struct {
|
type MoveTodosUpInstruction struct {
|
||||||
Sha string
|
Shas []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMoveTodoUpInstruction(sha string) Instruction {
|
func NewMoveTodosUpInstruction(shas []string) Instruction {
|
||||||
return &MoveTodoUpInstruction{
|
return &MoveTodosUpInstruction{
|
||||||
Sha: sha,
|
Shas: shas,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MoveTodoUpInstruction) Kind() DaemonKind {
|
func (self *MoveTodosUpInstruction) Kind() DaemonKind {
|
||||||
return DaemonKindMoveTodoUp
|
return DaemonKindMoveTodosUp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MoveTodoUpInstruction) SerializedInstructions() string {
|
func (self *MoveTodosUpInstruction) SerializedInstructions() string {
|
||||||
return serializeInstruction(self)
|
return serializeInstruction(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MoveTodoUpInstruction) run(common *common.Common) error {
|
func (self *MoveTodosUpInstruction) run(common *common.Common) error {
|
||||||
|
todosToMove := lo.Map(self.Shas, func(sha string, _ int) utils.Todo {
|
||||||
|
return utils.Todo{
|
||||||
|
Sha: sha,
|
||||||
|
Action: todo.Pick,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return handleInteractiveRebase(common, func(path string) error {
|
return handleInteractiveRebase(common, func(path string) error {
|
||||||
return utils.MoveTodoUp(path, self.Sha, todo.Pick, getCommentChar())
|
return utils.MoveTodosUp(path, todosToMove, getCommentChar())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type MoveTodoDownInstruction struct {
|
type MoveTodosDownInstruction struct {
|
||||||
Sha string
|
Shas []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMoveTodoDownInstruction(sha string) Instruction {
|
func NewMoveTodosDownInstruction(shas []string) Instruction {
|
||||||
return &MoveTodoDownInstruction{
|
return &MoveTodosDownInstruction{
|
||||||
Sha: sha,
|
Shas: shas,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MoveTodoDownInstruction) Kind() DaemonKind {
|
func (self *MoveTodosDownInstruction) Kind() DaemonKind {
|
||||||
return DaemonKindMoveTodoDown
|
return DaemonKindMoveTodosDown
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MoveTodoDownInstruction) SerializedInstructions() string {
|
func (self *MoveTodosDownInstruction) SerializedInstructions() string {
|
||||||
return serializeInstruction(self)
|
return serializeInstruction(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MoveTodoDownInstruction) run(common *common.Common) error {
|
func (self *MoveTodosDownInstruction) run(common *common.Common) error {
|
||||||
|
todosToMove := lo.Map(self.Shas, func(sha string, _ int) utils.Todo {
|
||||||
|
return utils.Todo{
|
||||||
|
Sha: sha,
|
||||||
|
Action: todo.Pick,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return handleInteractiveRebase(common, func(path string) error {
|
return handleInteractiveRebase(common, func(path string) error {
|
||||||
return utils.MoveTodoDown(path, self.Sha, todo.Pick, getCommentChar())
|
return utils.MoveTodosDown(path, todosToMove, getCommentChar())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/env"
|
"github.com/jesseduffield/lazygit/pkg/env"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TodoLine struct {
|
type TodoLine struct {
|
||||||
@@ -26,11 +26,11 @@ func (self *TodoLine) ToString() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TodoLinesToString(todoLines []TodoLine) string {
|
func TodoLinesToString(todoLines []TodoLine) string {
|
||||||
lines := slices.Map(todoLines, func(todoLine TodoLine) string {
|
lines := lo.Map(todoLines, func(todoLine TodoLine, _ int) string {
|
||||||
return todoLine.ToString()
|
return todoLine.ToString()
|
||||||
})
|
})
|
||||||
|
|
||||||
return strings.Join(slices.Reverse(lines), "")
|
return strings.Join(lo.Reverse(lines), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChangeTodoAction struct {
|
type ChangeTodoAction struct {
|
||||||
|
|||||||
+14
-15
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
@@ -17,7 +18,6 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/env"
|
"github.com/jesseduffield/lazygit/pkg/env"
|
||||||
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/logs/tail"
|
"github.com/jesseduffield/lazygit/pkg/logs/tail"
|
||||||
"github.com/jesseduffield/lazygit/pkg/secureexec"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -63,8 +63,17 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes
|
|||||||
log.Fatal(absRepoPath + " is not a valid git repository.")
|
log.Fatal(absRepoPath + " is not a valid git repository.")
|
||||||
}
|
}
|
||||||
|
|
||||||
cliArgs.WorkTree = absRepoPath
|
|
||||||
cliArgs.GitDir = filepath.Join(absRepoPath, ".git")
|
cliArgs.GitDir = filepath.Join(absRepoPath, ".git")
|
||||||
|
err = os.Chdir(absRepoPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to change directory to %s: %v", absRepoPath, err)
|
||||||
|
}
|
||||||
|
} else if cliArgs.WorkTree != "" {
|
||||||
|
env.SetWorkTreeEnv(cliArgs.WorkTree)
|
||||||
|
|
||||||
|
if err := os.Chdir(cliArgs.WorkTree); err != nil {
|
||||||
|
log.Fatalf("Failed to change directory to %s: %v", cliArgs.WorkTree, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cliArgs.CustomConfigFile != "" {
|
if cliArgs.CustomConfigFile != "" {
|
||||||
@@ -75,10 +84,6 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes
|
|||||||
os.Setenv("CONFIG_DIR", cliArgs.UseConfigDir)
|
os.Setenv("CONFIG_DIR", cliArgs.UseConfigDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cliArgs.WorkTree != "" {
|
|
||||||
env.SetGitWorkTreeEnv(cliArgs.WorkTree)
|
|
||||||
}
|
|
||||||
|
|
||||||
if cliArgs.GitDir != "" {
|
if cliArgs.GitDir != "" {
|
||||||
env.SetGitDirEnv(cliArgs.GitDir)
|
env.SetGitDirEnv(cliArgs.GitDir)
|
||||||
}
|
}
|
||||||
@@ -115,12 +120,6 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cliArgs.WorkTree != "" {
|
|
||||||
if err := os.Chdir(cliArgs.WorkTree); err != nil {
|
|
||||||
log.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDir, err := os.MkdirTemp("", "lazygit-*")
|
tempDir, err := os.MkdirTemp("", "lazygit-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
@@ -181,10 +180,10 @@ func parseCliArgsAndEnvVars() *cliArgs {
|
|||||||
useConfigDir := ""
|
useConfigDir := ""
|
||||||
flaggy.String(&useConfigDir, "ucd", "use-config-dir", "override default config directory with provided directory")
|
flaggy.String(&useConfigDir, "ucd", "use-config-dir", "override default config directory with provided directory")
|
||||||
|
|
||||||
workTree := ""
|
workTree := os.Getenv("GIT_WORK_TREE")
|
||||||
flaggy.String(&workTree, "w", "work-tree", "equivalent of the --work-tree git argument")
|
flaggy.String(&workTree, "w", "work-tree", "equivalent of the --work-tree git argument")
|
||||||
|
|
||||||
gitDir := ""
|
gitDir := os.Getenv("GIT_DIR")
|
||||||
flaggy.String(&gitDir, "g", "git-dir", "equivalent of the --git-dir git argument")
|
flaggy.String(&gitDir, "g", "git-dir", "equivalent of the --git-dir git argument")
|
||||||
|
|
||||||
customConfigFile := ""
|
customConfigFile := ""
|
||||||
@@ -277,7 +276,7 @@ func mergeBuildInfo(buildInfo *BuildInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getGitVersionInfo() string {
|
func getGitVersionInfo() string {
|
||||||
cmd := secureexec.Command("git", "--version")
|
cmd := exec.Command("git", "--version")
|
||||||
stdout, _ := cmd.Output()
|
stdout, _ := cmd.Output()
|
||||||
gitVersion := strings.Trim(strings.TrimPrefix(string(stdout), "git version "), " \r\n")
|
gitVersion := strings.Trim(strings.TrimPrefix(string(stdout), "git version "), " \r\n")
|
||||||
return gitVersion
|
return gitVersion
|
||||||
|
|||||||
+7
-3
@@ -3,8 +3,8 @@ package app
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type errorMapping struct {
|
type errorMapping struct {
|
||||||
@@ -18,7 +18,7 @@ func knownError(tr *i18n.TranslationSet, err error) (string, bool) {
|
|||||||
|
|
||||||
knownErrorMessages := []string{tr.MinGitVersionError}
|
knownErrorMessages := []string{tr.MinGitVersionError}
|
||||||
|
|
||||||
if slices.Contains(knownErrorMessages, errorMessage) {
|
if lo.Contains(knownErrorMessages, errorMessage) {
|
||||||
return errorMessage, true
|
return errorMessage, true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,9 +27,13 @@ func knownError(tr *i18n.TranslationSet, err error) (string, bool) {
|
|||||||
originalError: "fatal: not a git repository",
|
originalError: "fatal: not a git repository",
|
||||||
newError: tr.NotARepository,
|
newError: tr.NotARepository,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
originalError: "getwd: no such file or directory",
|
||||||
|
newError: tr.WorkingDirectoryDoesNotExist,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if mapping, ok := slices.Find(mappings, func(mapping errorMapping) bool {
|
if mapping, ok := lo.Find(mappings, func(mapping errorMapping) bool {
|
||||||
return strings.Contains(errorMessage, mapping.originalError)
|
return strings.Contains(errorMessage, mapping.originalError)
|
||||||
}); ok {
|
}); ok {
|
||||||
return mapping.newError, true
|
return mapping.newError, true
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
package cheatsheet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Check() {
|
|
||||||
dir := GetKeybindingsDir()
|
|
||||||
tmpDir := filepath.Join(os.TempDir(), "lazygit_cheatsheet")
|
|
||||||
err := os.RemoveAll(tmpDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err)
|
|
||||||
}
|
|
||||||
err = os.Mkdir(tmpDir, 0o700)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
generateAtDir(tmpDir)
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
actualContent := obtainContent(dir)
|
|
||||||
expectedContent := obtainContent(tmpDir)
|
|
||||||
|
|
||||||
if expectedContent == "" {
|
|
||||||
log.Fatal("empty expected content")
|
|
||||||
}
|
|
||||||
|
|
||||||
if actualContent != expectedContent {
|
|
||||||
err := difflib.WriteUnifiedDiff(os.Stdout, difflib.UnifiedDiff{
|
|
||||||
A: difflib.SplitLines(expectedContent),
|
|
||||||
B: difflib.SplitLines(actualContent),
|
|
||||||
FromFile: "Expected",
|
|
||||||
FromDate: "",
|
|
||||||
ToFile: "Actual",
|
|
||||||
ToDate: "",
|
|
||||||
Context: 1,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("\nCheatsheets are out of date. Please run `%s` at the project root and commit the changes. If you run the script and no keybindings files are updated as a result, try rebasing onto master and trying again.\n", CommandToRun())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("\nCheatsheets are up to date")
|
|
||||||
}
|
|
||||||
|
|
||||||
func obtainContent(dir string) string {
|
|
||||||
re := regexp.MustCompile(`Keybindings_\w+\.md$`)
|
|
||||||
|
|
||||||
content := ""
|
|
||||||
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
|
||||||
if re.MatchString(path) {
|
|
||||||
bytes, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err)
|
|
||||||
}
|
|
||||||
content += fmt.Sprintf("\n%s\n\n", filepath.Base(path))
|
|
||||||
content += string(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error occurred while checking if cheatsheets are up to date: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
+22
-24
@@ -1,10 +1,12 @@
|
|||||||
// This "script" generates a file called Keybindings_{{.LANG}}.md
|
//go:generate go run generator.go
|
||||||
// in current working directory.
|
|
||||||
|
// This "script" generates files called Keybindings_{{.LANG}}.md
|
||||||
|
// in the docs/keybindings directory.
|
||||||
//
|
//
|
||||||
// The content of this generated file is a keybindings cheatsheet.
|
// The content of these generated files is a keybindings cheatsheet.
|
||||||
//
|
//
|
||||||
// To generate cheatsheet in english run:
|
// To generate the cheatsheets, run:
|
||||||
// go run scripts/generate_cheatsheet.go
|
// go generate pkg/cheatsheet/generate.go
|
||||||
|
|
||||||
package cheatsheet
|
package cheatsheet
|
||||||
|
|
||||||
@@ -12,10 +14,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/maps"
|
"github.com/jesseduffield/generics/maps"
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazycore/pkg/utils"
|
"github.com/jesseduffield/lazycore/pkg/utils"
|
||||||
"github.com/jesseduffield/lazygit/pkg/app"
|
"github.com/jesseduffield/lazygit/pkg/app"
|
||||||
"github.com/jesseduffield/lazygit/pkg/config"
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bindingSection struct {
|
type bindingSection struct {
|
||||||
@@ -42,7 +43,7 @@ type headerWithBindings struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CommandToRun() string {
|
func CommandToRun() string {
|
||||||
return "go run scripts/cheatsheet/main.go generate"
|
return "go generate ./..."
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetKeybindingsDir() string {
|
func GetKeybindingsDir() string {
|
||||||
@@ -59,7 +60,7 @@ func generateAtDir(cheatsheetDir string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
mApp, _ := app.NewApp(mConfig, common)
|
mApp, _ := app.NewApp(mConfig, nil, common)
|
||||||
path := cheatsheetDir + "/Keybindings_" + lang + ".md"
|
path := cheatsheetDir + "/Keybindings_" + lang + ".md"
|
||||||
file, err := os.Create(path)
|
file, err := os.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -101,7 +102,7 @@ func localisedTitle(tr *i18n.TranslationSet, str string) string {
|
|||||||
"reflogCommits": tr.ReflogCommitsTitle,
|
"reflogCommits": tr.ReflogCommitsTitle,
|
||||||
"tags": tr.TagsTitle,
|
"tags": tr.TagsTitle,
|
||||||
"commitFiles": tr.CommitFilesTitle,
|
"commitFiles": tr.CommitFilesTitle,
|
||||||
"commitMessage": tr.CommitMessageTitle,
|
"commitMessage": tr.CommitSummaryTitle,
|
||||||
"commitDescription": tr.CommitDescriptionTitle,
|
"commitDescription": tr.CommitDescriptionTitle,
|
||||||
"commits": tr.CommitsTitle,
|
"commits": tr.CommitsTitle,
|
||||||
"confirmation": tr.ConfirmationTitle,
|
"confirmation": tr.ConfirmationTitle,
|
||||||
@@ -116,6 +117,7 @@ func localisedTitle(tr *i18n.TranslationSet, str string) string {
|
|||||||
"stash": tr.StashTitle,
|
"stash": tr.StashTitle,
|
||||||
"suggestions": tr.SuggestionsCheatsheetTitle,
|
"suggestions": tr.SuggestionsCheatsheetTitle,
|
||||||
"extras": tr.ExtrasTitle,
|
"extras": tr.ExtrasTitle,
|
||||||
|
"worktrees": tr.WorktreesTitle,
|
||||||
}
|
}
|
||||||
|
|
||||||
title, ok := contextTitleMap[str]
|
title, ok := contextTitleMap[str]
|
||||||
@@ -128,7 +130,7 @@ func localisedTitle(tr *i18n.TranslationSet, str string) string {
|
|||||||
|
|
||||||
func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*bindingSection {
|
func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*bindingSection {
|
||||||
excludedViews := []string{"stagingSecondary", "patchBuildingSecondary"}
|
excludedViews := []string{"stagingSecondary", "patchBuildingSecondary"}
|
||||||
bindingsToDisplay := slices.Filter(bindings, func(binding *types.Binding) bool {
|
bindingsToDisplay := lo.Filter(bindings, func(binding *types.Binding, _ int) bool {
|
||||||
if lo.Contains(excludedViews, binding.ViewName) {
|
if lo.Contains(excludedViews, binding.ViewName) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -161,7 +163,7 @@ func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*b
|
|||||||
return a.header.title < b.header.title
|
return a.header.title < b.header.title
|
||||||
})
|
})
|
||||||
|
|
||||||
return slices.Map(bindingGroups, func(hb headerWithBindings) *bindingSection {
|
return lo.Map(bindingGroups, func(hb headerWithBindings, _ int) *bindingSection {
|
||||||
return &bindingSection{
|
return &bindingSection{
|
||||||
title: hb.header.title,
|
title: hb.header.title,
|
||||||
bindings: hb.bindings,
|
bindings: hb.bindings,
|
||||||
@@ -188,11 +190,11 @@ func formatSections(tr *i18n.TranslationSet, bindingSections []*bindingSection)
|
|||||||
|
|
||||||
for _, section := range bindingSections {
|
for _, section := range bindingSections {
|
||||||
content += formatTitle(section.title)
|
content += formatTitle(section.title)
|
||||||
content += "<pre>\n"
|
content += "| Key | Action | Info |\n"
|
||||||
|
content += "|-----|--------|-------------|\n"
|
||||||
for _, binding := range section.bindings {
|
for _, binding := range section.bindings {
|
||||||
content += formatBinding(binding)
|
content += formatBinding(binding)
|
||||||
}
|
}
|
||||||
content += "</pre>\n"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return content
|
return content
|
||||||
@@ -203,19 +205,15 @@ func formatTitle(title string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func formatBinding(binding *types.Binding) string {
|
func formatBinding(binding *types.Binding) string {
|
||||||
result := fmt.Sprintf(" <kbd>%s</kbd>: %s", escapeAngleBrackets(keybindings.LabelFromKey(binding.Key)), binding.Description)
|
action := keybindings.LabelFromKey(binding.Key)
|
||||||
|
description := binding.Description
|
||||||
if binding.Alternative != "" {
|
if binding.Alternative != "" {
|
||||||
result += fmt.Sprintf(" (%s)", binding.Alternative)
|
action += fmt.Sprintf(" (%s)", binding.Alternative)
|
||||||
}
|
}
|
||||||
result += "\n"
|
|
||||||
|
|
||||||
return result
|
// Use backticks for keyboard keys. Two backticks are needed with an inner space
|
||||||
}
|
// to escape a key that is itself a backtick.
|
||||||
|
return fmt.Sprintf("| `` %s `` | %s | %s |\n", action, description, binding.Tooltip)
|
||||||
func escapeAngleBrackets(str string) string {
|
|
||||||
result := strings.ReplaceAll(str, ">", ">")
|
|
||||||
result = strings.ReplaceAll(result, "<", "<")
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func italicize(str string) string {
|
func italicize(str string) string {
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/cheatsheet"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("Generating cheatsheets in %s...\n", cheatsheet.GetKeybindingsDir())
|
||||||
|
cheatsheet.Generate()
|
||||||
|
}
|
||||||
+32
-129
@@ -2,11 +2,9 @@ package commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/sasha-s/go-deadlock"
|
|
||||||
|
|
||||||
gogit "github.com/jesseduffield/go-git/v5"
|
gogit "github.com/jesseduffield/go-git/v5"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
@@ -14,12 +12,12 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/env"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GitCommand is our main git interface
|
// GitCommand is our main git interface
|
||||||
type GitCommand struct {
|
type GitCommand struct {
|
||||||
|
Blame *git_commands.BlameCommands
|
||||||
Branch *git_commands.BranchCommands
|
Branch *git_commands.BranchCommands
|
||||||
Commit *git_commands.CommitCommands
|
Commit *git_commands.CommitCommands
|
||||||
Config *git_commands.ConfigCommands
|
Config *git_commands.ConfigCommands
|
||||||
@@ -37,6 +35,9 @@ type GitCommand struct {
|
|||||||
Tag *git_commands.TagCommands
|
Tag *git_commands.TagCommands
|
||||||
WorkingTree *git_commands.WorkingTreeCommands
|
WorkingTree *git_commands.WorkingTreeCommands
|
||||||
Bisect *git_commands.BisectCommands
|
Bisect *git_commands.BisectCommands
|
||||||
|
Worktree *git_commands.WorktreeCommands
|
||||||
|
Version *git_commands.GitVersion
|
||||||
|
RepoPaths *git_commands.RepoPaths
|
||||||
|
|
||||||
Loaders Loaders
|
Loaders Loaders
|
||||||
}
|
}
|
||||||
@@ -50,6 +51,7 @@ type Loaders struct {
|
|||||||
RemoteLoader *git_commands.RemoteLoader
|
RemoteLoader *git_commands.RemoteLoader
|
||||||
StashLoader *git_commands.StashLoader
|
StashLoader *git_commands.StashLoader
|
||||||
TagLoader *git_commands.TagLoader
|
TagLoader *git_commands.TagLoader
|
||||||
|
Worktrees *git_commands.WorktreeLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGitCommand(
|
func NewGitCommand(
|
||||||
@@ -57,19 +59,25 @@ func NewGitCommand(
|
|||||||
version *git_commands.GitVersion,
|
version *git_commands.GitVersion,
|
||||||
osCommand *oscommands.OSCommand,
|
osCommand *oscommands.OSCommand,
|
||||||
gitConfig git_config.IGitConfig,
|
gitConfig git_config.IGitConfig,
|
||||||
syncMutex *deadlock.Mutex,
|
|
||||||
) (*GitCommand, error) {
|
) (*GitCommand, error) {
|
||||||
if err := navigateToRepoRootDirectory(os.Stat, os.Chdir); err != nil {
|
repoPaths, err := git_commands.GetRepoPaths(osCommand.Cmd, version)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("Error getting repo paths: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := setupRepository(gogit.PlainOpenWithOptions, gogit.PlainOpenOptions{DetectDotGit: false, EnableDotGitCommonDir: true}, cmn.Tr.GitconfigParseErr)
|
err = os.Chdir(repoPaths.WorktreePath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, utils.WrapError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dotGitDir, err := findDotGitDir(os.Stat, os.ReadFile)
|
repository, err := gogit.PlainOpenWithOptions(
|
||||||
|
repoPaths.WorktreeGitDirPath(),
|
||||||
|
&gogit.PlainOpenOptions{DetectDotGit: false, EnableDotGitCommonDir: true},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), `unquoted '\' must be followed by new line`) {
|
||||||
|
return nil, errors.New(cmn.Tr.GitconfigParseErr)
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,9 +86,8 @@ func NewGitCommand(
|
|||||||
version,
|
version,
|
||||||
osCommand,
|
osCommand,
|
||||||
gitConfig,
|
gitConfig,
|
||||||
dotGitDir,
|
repoPaths,
|
||||||
repo,
|
repository,
|
||||||
syncMutex,
|
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,9 +96,8 @@ func NewGitCommandAux(
|
|||||||
version *git_commands.GitVersion,
|
version *git_commands.GitVersion,
|
||||||
osCommand *oscommands.OSCommand,
|
osCommand *oscommands.OSCommand,
|
||||||
gitConfig git_config.IGitConfig,
|
gitConfig git_config.IGitConfig,
|
||||||
dotGitDir string,
|
repoPaths *git_commands.RepoPaths,
|
||||||
repo *gogit.Repository,
|
repo *gogit.Repository,
|
||||||
syncMutex *deadlock.Mutex,
|
|
||||||
) *GitCommand {
|
) *GitCommand {
|
||||||
cmd := NewGitCmdObjBuilder(cmn.Log, osCommand.Cmd)
|
cmd := NewGitCmdObjBuilder(cmn.Log, osCommand.Cmd)
|
||||||
|
|
||||||
@@ -102,9 +108,9 @@ func NewGitCommandAux(
|
|||||||
// common ones are: cmn, osCommand, dotGitDir, configCommands
|
// common ones are: cmn, osCommand, dotGitDir, configCommands
|
||||||
configCommands := git_commands.NewConfigCommands(cmn, gitConfig, repo)
|
configCommands := git_commands.NewConfigCommands(cmn, gitConfig, repo)
|
||||||
|
|
||||||
fileLoader := git_commands.NewFileLoader(cmn, cmd, configCommands)
|
gitCommon := git_commands.NewGitCommon(cmn, version, cmd, osCommand, repoPaths, repo, configCommands)
|
||||||
|
|
||||||
gitCommon := git_commands.NewGitCommon(cmn, version, cmd, osCommand, dotGitDir, repo, configCommands, syncMutex)
|
fileLoader := git_commands.NewFileLoader(gitCommon, cmd, configCommands)
|
||||||
statusCommands := git_commands.NewStatusCommands(gitCommon)
|
statusCommands := git_commands.NewStatusCommands(gitCommon)
|
||||||
flowCommands := git_commands.NewFlowCommands(gitCommon)
|
flowCommands := git_commands.NewFlowCommands(gitCommon)
|
||||||
remoteCommands := git_commands.NewRemoteCommands(gitCommon)
|
remoteCommands := git_commands.NewRemoteCommands(gitCommon)
|
||||||
@@ -121,22 +127,24 @@ func NewGitCommandAux(
|
|||||||
stashCommands := git_commands.NewStashCommands(gitCommon, fileLoader, workingTreeCommands)
|
stashCommands := git_commands.NewStashCommands(gitCommon, fileLoader, workingTreeCommands)
|
||||||
patchBuilder := patch.NewPatchBuilder(cmn.Log,
|
patchBuilder := patch.NewPatchBuilder(cmn.Log,
|
||||||
func(from string, to string, reverse bool, filename string, plain bool) (string, error) {
|
func(from string, to string, reverse bool, filename string, plain bool) (string, error) {
|
||||||
// TODO: make patch builder take Gui.IgnoreWhitespaceInDiffView into
|
return workingTreeCommands.ShowFileDiff(from, to, reverse, filename, plain)
|
||||||
// account. For now we just pass false.
|
|
||||||
return workingTreeCommands.ShowFileDiff(from, to, reverse, filename, plain, false)
|
|
||||||
})
|
})
|
||||||
patchCommands := git_commands.NewPatchCommands(gitCommon, rebaseCommands, commitCommands, statusCommands, stashCommands, patchBuilder)
|
patchCommands := git_commands.NewPatchCommands(gitCommon, rebaseCommands, commitCommands, statusCommands, stashCommands, patchBuilder)
|
||||||
bisectCommands := git_commands.NewBisectCommands(gitCommon)
|
bisectCommands := git_commands.NewBisectCommands(gitCommon)
|
||||||
|
worktreeCommands := git_commands.NewWorktreeCommands(gitCommon)
|
||||||
|
blameCommands := git_commands.NewBlameCommands(gitCommon)
|
||||||
|
|
||||||
branchLoader := git_commands.NewBranchLoader(cmn, cmd, branchCommands.CurrentBranchInfo, configCommands)
|
branchLoader := git_commands.NewBranchLoader(cmn, cmd, branchCommands.CurrentBranchInfo, configCommands)
|
||||||
commitFileLoader := git_commands.NewCommitFileLoader(cmn, cmd)
|
commitFileLoader := git_commands.NewCommitFileLoader(cmn, cmd)
|
||||||
commitLoader := git_commands.NewCommitLoader(cmn, cmd, dotGitDir, statusCommands.RebaseMode, gitCommon)
|
commitLoader := git_commands.NewCommitLoader(cmn, cmd, statusCommands.RebaseMode, gitCommon)
|
||||||
reflogCommitLoader := git_commands.NewReflogCommitLoader(cmn, cmd)
|
reflogCommitLoader := git_commands.NewReflogCommitLoader(cmn, cmd)
|
||||||
remoteLoader := git_commands.NewRemoteLoader(cmn, cmd, repo.Remotes)
|
remoteLoader := git_commands.NewRemoteLoader(cmn, cmd, repo.Remotes)
|
||||||
|
worktreeLoader := git_commands.NewWorktreeLoader(gitCommon)
|
||||||
stashLoader := git_commands.NewStashLoader(cmn, cmd)
|
stashLoader := git_commands.NewStashLoader(cmn, cmd)
|
||||||
tagLoader := git_commands.NewTagLoader(cmn, cmd)
|
tagLoader := git_commands.NewTagLoader(cmn, cmd)
|
||||||
|
|
||||||
return &GitCommand{
|
return &GitCommand{
|
||||||
|
Blame: blameCommands,
|
||||||
Branch: branchCommands,
|
Branch: branchCommands,
|
||||||
Commit: commitCommands,
|
Commit: commitCommands,
|
||||||
Config: configCommands,
|
Config: configCommands,
|
||||||
@@ -154,6 +162,8 @@ func NewGitCommandAux(
|
|||||||
Tag: tagCommands,
|
Tag: tagCommands,
|
||||||
Bisect: bisectCommands,
|
Bisect: bisectCommands,
|
||||||
WorkingTree: workingTreeCommands,
|
WorkingTree: workingTreeCommands,
|
||||||
|
Worktree: worktreeCommands,
|
||||||
|
Version: version,
|
||||||
Loaders: Loaders{
|
Loaders: Loaders{
|
||||||
BranchLoader: branchLoader,
|
BranchLoader: branchLoader,
|
||||||
CommitFileLoader: commitFileLoader,
|
CommitFileLoader: commitFileLoader,
|
||||||
@@ -161,121 +171,14 @@ func NewGitCommandAux(
|
|||||||
FileLoader: fileLoader,
|
FileLoader: fileLoader,
|
||||||
ReflogCommitLoader: reflogCommitLoader,
|
ReflogCommitLoader: reflogCommitLoader,
|
||||||
RemoteLoader: remoteLoader,
|
RemoteLoader: remoteLoader,
|
||||||
|
Worktrees: worktreeLoader,
|
||||||
StashLoader: stashLoader,
|
StashLoader: stashLoader,
|
||||||
TagLoader: tagLoader,
|
TagLoader: tagLoader,
|
||||||
},
|
},
|
||||||
|
RepoPaths: repoPaths,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func navigateToRepoRootDirectory(stat func(string) (os.FileInfo, error), chdir func(string) error) error {
|
|
||||||
gitDir := env.GetGitDirEnv()
|
|
||||||
if gitDir != "" {
|
|
||||||
// we've been given the git directory explicitly so no need to navigate to it
|
|
||||||
_, err := stat(gitDir)
|
|
||||||
if err != nil {
|
|
||||||
return utils.WrapError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// we haven't been given the git dir explicitly so we assume it's in the current working directory as `.git/` (or an ancestor directory)
|
|
||||||
|
|
||||||
for {
|
|
||||||
_, err := stat(".git")
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return utils.WrapError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = chdir(".."); err != nil {
|
|
||||||
return utils.WrapError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPath, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
atRoot := currentPath == filepath.Dir(currentPath)
|
|
||||||
if atRoot {
|
|
||||||
// we should never really land here: the code that creates GitCommand should
|
|
||||||
// verify we're in a git directory
|
|
||||||
return errors.New("Must open lazygit in a git repository")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolvePath takes a path containing a symlink and returns the true path
|
|
||||||
func resolvePath(path string) (string, error) {
|
|
||||||
l, err := os.Lstat(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if l.Mode()&os.ModeSymlink == 0 {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return filepath.EvalSymlinks(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupRepository(openGitRepository func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error), options gogit.PlainOpenOptions, gitConfigParseErrorStr string) (*gogit.Repository, error) {
|
|
||||||
unresolvedPath := env.GetGitDirEnv()
|
|
||||||
if unresolvedPath == "" {
|
|
||||||
var err error
|
|
||||||
unresolvedPath, err = os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := resolvePath(unresolvedPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
repository, err := openGitRepository(path, &options)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), `unquoted '\' must be followed by new line`) {
|
|
||||||
return nil, errors.New(gitConfigParseErrorStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return repository, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func findDotGitDir(stat func(string) (os.FileInfo, error), readFile func(filename string) ([]byte, error)) (string, error) {
|
|
||||||
if env.GetGitDirEnv() != "" {
|
|
||||||
return env.GetGitDirEnv(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := stat(".git")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.IsDir() {
|
|
||||||
return ".git", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fileBytes, err := readFile(".git")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
fileContent := string(fileBytes)
|
|
||||||
if !strings.HasPrefix(fileContent, "gitdir: ") {
|
|
||||||
return "", errors.New(".git is a file which suggests we are in a submodule or a worktree but the file's contents do not contain a gitdir pointing to the actual .git directory")
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(strings.TrimPrefix(fileContent, "gitdir: ")), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func VerifyInGitRepo(osCommand *oscommands.OSCommand) error {
|
func VerifyInGitRepo(osCommand *oscommands.OSCommand) error {
|
||||||
return osCommand.Cmd.New(git_commands.NewGitCmd("rev-parse").Arg("--git-dir").ToArgv()).DontLog().Run()
|
return osCommand.Cmd.New(git_commands.NewGitCmd("rev-parse").Arg("--git-dir").ToArgv()).DontLog().Run()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,16 @@ func NewBisectCommands(gitCommon *GitCommon) *BisectCommands {
|
|||||||
// This command is pretty cheap to run so we're not storing the result anywhere.
|
// This command is pretty cheap to run so we're not storing the result anywhere.
|
||||||
// But if it becomes problematic we can chang that.
|
// But if it becomes problematic we can chang that.
|
||||||
func (self *BisectCommands) GetInfo() *BisectInfo {
|
func (self *BisectCommands) GetInfo() *BisectInfo {
|
||||||
|
return self.GetInfoForGitDir(self.repoPaths.WorktreeGitDirPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo {
|
||||||
var err error
|
var err error
|
||||||
info := &BisectInfo{started: false, log: self.Log, newTerm: "bad", oldTerm: "good"}
|
info := &BisectInfo{started: false, log: self.Log, newTerm: "bad", oldTerm: "good"}
|
||||||
// we return nil if we're not in a git bisect session.
|
// we return nil if we're not in a git bisect session.
|
||||||
// we know we're in a session by the presence of a .git/BISECT_START file
|
// we know we're in a session by the presence of a .git/BISECT_START file
|
||||||
|
|
||||||
bisectStartPath := filepath.Join(self.dotGitDir, "BISECT_START")
|
bisectStartPath := filepath.Join(gitDir, "BISECT_START")
|
||||||
exists, err := self.os.FileExists(bisectStartPath)
|
exists, err := self.os.FileExists(bisectStartPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||||
@@ -44,7 +48,7 @@ func (self *BisectCommands) GetInfo() *BisectInfo {
|
|||||||
info.started = true
|
info.started = true
|
||||||
info.start = strings.TrimSpace(string(startContent))
|
info.start = strings.TrimSpace(string(startContent))
|
||||||
|
|
||||||
termsContent, err := os.ReadFile(filepath.Join(self.dotGitDir, "BISECT_TERMS"))
|
termsContent, err := os.ReadFile(filepath.Join(gitDir, "BISECT_TERMS"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// old git versions won't have this file so we default to bad/good
|
// old git versions won't have this file so we default to bad/good
|
||||||
} else {
|
} else {
|
||||||
@@ -53,7 +57,7 @@ func (self *BisectCommands) GetInfo() *BisectInfo {
|
|||||||
info.oldTerm = splitContent[1]
|
info.oldTerm = splitContent[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
bisectRefsDir := filepath.Join(self.dotGitDir, "refs", "bisect")
|
bisectRefsDir := filepath.Join(gitDir, "refs", "bisect")
|
||||||
files, err := os.ReadDir(bisectRefsDir)
|
files, err := os.ReadDir(bisectRefsDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||||
@@ -85,7 +89,7 @@ func (self *BisectCommands) GetInfo() *BisectInfo {
|
|||||||
info.statusMap[sha] = status
|
info.statusMap[sha] = status
|
||||||
}
|
}
|
||||||
|
|
||||||
currentContent, err := os.ReadFile(filepath.Join(self.dotGitDir, "BISECT_EXPECTED_REV"))
|
currentContent, err := os.ReadFile(filepath.Join(gitDir, "BISECT_EXPECTED_REV"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
self.Log.Infof("error getting git bisect info: %s", err.Error())
|
||||||
return info
|
return info
|
||||||
@@ -121,6 +125,15 @@ func (self *BisectCommands) Start() error {
|
|||||||
return self.cmd.New(cmdArgs).StreamOutput().Run()
|
return self.cmd.New(cmdArgs).StreamOutput().Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *BisectCommands) StartWithTerms(oldTerm string, newTerm string) error {
|
||||||
|
cmdArgs := NewGitCmd("bisect").Arg("start").
|
||||||
|
Arg("--term-old=" + oldTerm).
|
||||||
|
Arg("--term-new=" + newTerm).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).StreamOutput().Run()
|
||||||
|
}
|
||||||
|
|
||||||
// tells us whether we've found our problem commit(s). We return a string slice of
|
// tells us whether we've found our problem commit(s). We return a string slice of
|
||||||
// commit sha's if we're done, and that slice may have more that one item if
|
// commit sha's if we're done, and that slice may have more that one item if
|
||||||
// skipped commits are involved.
|
// skipped commits are involved.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package git_commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/generics/maps"
|
"github.com/jesseduffield/generics/maps"
|
||||||
"github.com/jesseduffield/generics/slices"
|
"github.com/samber/lo"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -97,5 +97,5 @@ func (self *BisectInfo) Bisecting() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return slices.Contains(maps.Values(self.statusMap), BisectStatusOld)
|
return lo.Contains(maps.Values(self.statusMap), BisectStatusOld)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package git_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BlameCommands struct {
|
||||||
|
*GitCommon
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBlameCommands(gitCommon *GitCommon) *BlameCommands {
|
||||||
|
return &BlameCommands{
|
||||||
|
GitCommon: gitCommon,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blame a range of lines. For each line, output the hash of the commit where
|
||||||
|
// the line last changed, then a space, then a description of the commit (author
|
||||||
|
// and date), another space, and then the line. For example:
|
||||||
|
//
|
||||||
|
// ac90ebac688fe8bc2ffd922157a9d2c54681d2aa (Stefan Haller 2023-08-01 14:54:56 +0200 11) func NewBlameCommands(gitCommon *GitCommon) *BlameCommands {
|
||||||
|
// ac90ebac688fe8bc2ffd922157a9d2c54681d2aa (Stefan Haller 2023-08-01 14:54:56 +0200 12) return &BlameCommands{
|
||||||
|
// ac90ebac688fe8bc2ffd922157a9d2c54681d2aa (Stefan Haller 2023-08-01 14:54:56 +0200 13) GitCommon: gitCommon,
|
||||||
|
func (self *BlameCommands) BlameLineRange(filename string, commit string, firstLine int, numLines int) (string, error) {
|
||||||
|
cmdArgs := NewGitCmd("blame").
|
||||||
|
Arg("-l").
|
||||||
|
Arg(fmt.Sprintf("-L%d,+%d", firstLine, numLines)).
|
||||||
|
Arg(commit).
|
||||||
|
Arg("--").
|
||||||
|
Arg(filename)
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs.ToArgv()).RunWithOutput()
|
||||||
|
}
|
||||||
@@ -70,8 +70,23 @@ func (self *BranchCommands) CurrentBranchInfo() (BranchInfo, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete delete branch
|
// CurrentBranchName get name of current branch
|
||||||
func (self *BranchCommands) Delete(branch string, force bool) error {
|
func (self *BranchCommands) CurrentBranchName() (string, error) {
|
||||||
|
cmdArgs := NewGitCmd("rev-parse").
|
||||||
|
Arg("--abbrev-ref").
|
||||||
|
Arg("--verify").
|
||||||
|
Arg("HEAD").
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
output, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
|
if err == nil {
|
||||||
|
return strings.TrimSpace(output), nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalDelete delete branch locally
|
||||||
|
func (self *BranchCommands) LocalDelete(branch string, force bool) error {
|
||||||
cmdArgs := NewGitCmd("branch").
|
cmdArgs := NewGitCmd("branch").
|
||||||
ArgIfElse(force, "-D", "-d").
|
ArgIfElse(force, "-D", "-d").
|
||||||
Arg(branch).
|
Arg(branch).
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ package git_commands
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/set"
|
"github.com/jesseduffield/generics/set"
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/go-git/v5/config"
|
"github.com/jesseduffield/go-git/v5/config"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// context:
|
// context:
|
||||||
@@ -62,33 +63,40 @@ func NewBranchLoader(
|
|||||||
func (self *BranchLoader) Load(reflogCommits []*models.Commit) ([]*models.Branch, error) {
|
func (self *BranchLoader) Load(reflogCommits []*models.Commit) ([]*models.Branch, error) {
|
||||||
branches := self.obtainBranches()
|
branches := self.obtainBranches()
|
||||||
|
|
||||||
reflogBranches := self.obtainReflogBranches(reflogCommits)
|
if self.AppState.LocalBranchSortOrder == "recency" {
|
||||||
|
reflogBranches := self.obtainReflogBranches(reflogCommits)
|
||||||
// loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches
|
// loop through reflog branches. If there is a match, merge them, then remove it from the branches and keep it in the reflog branches
|
||||||
branchesWithRecency := make([]*models.Branch, 0)
|
branchesWithRecency := make([]*models.Branch, 0)
|
||||||
outer:
|
outer:
|
||||||
for _, reflogBranch := range reflogBranches {
|
for _, reflogBranch := range reflogBranches {
|
||||||
for j, branch := range branches {
|
for j, branch := range branches {
|
||||||
if branch.Head {
|
if branch.Head {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.EqualFold(reflogBranch.Name, branch.Name) {
|
if strings.EqualFold(reflogBranch.Name, branch.Name) {
|
||||||
branch.Recency = reflogBranch.Recency
|
branch.Recency = reflogBranch.Recency
|
||||||
branchesWithRecency = append(branchesWithRecency, branch)
|
branchesWithRecency = append(branchesWithRecency, branch)
|
||||||
branches = slices.Remove(branches, j)
|
branches = utils.Remove(branches, j)
|
||||||
continue outer
|
continue outer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
branches = slices.Prepend(branches, branchesWithRecency...)
|
// Sort branches that don't have a recency value alphabetically
|
||||||
|
// (we're really doing this for the sake of deterministic behaviour across git versions)
|
||||||
|
slices.SortFunc(branches, func(a *models.Branch, b *models.Branch) bool {
|
||||||
|
return a.Name < b.Name
|
||||||
|
})
|
||||||
|
|
||||||
|
branches = utils.Prepend(branches, branchesWithRecency...)
|
||||||
|
}
|
||||||
|
|
||||||
foundHead := false
|
foundHead := false
|
||||||
for i, branch := range branches {
|
for i, branch := range branches {
|
||||||
if branch.Head {
|
if branch.Head {
|
||||||
foundHead = true
|
foundHead = true
|
||||||
branch.Recency = " *"
|
branch.Recency = " *"
|
||||||
branches = slices.Move(branches, i, 0)
|
branches = utils.Move(branches, i, 0)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +105,7 @@ outer:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
branches = slices.Prepend(branches, &models.Branch{Name: info.RefName, DisplayName: info.DisplayName, Head: true, DetachedHead: info.DetachedHead, Recency: " *"})
|
branches = utils.Prepend(branches, &models.Branch{Name: info.RefName, DisplayName: info.DisplayName, Head: true, DetachedHead: info.DetachedHead, Recency: " *"})
|
||||||
}
|
}
|
||||||
|
|
||||||
configBranches, err := self.config.Branches()
|
configBranches, err := self.config.Branches()
|
||||||
@@ -125,7 +133,7 @@ func (self *BranchLoader) obtainBranches() []*models.Branch {
|
|||||||
trimmedOutput := strings.TrimSpace(output)
|
trimmedOutput := strings.TrimSpace(output)
|
||||||
outputLines := strings.Split(trimmedOutput, "\n")
|
outputLines := strings.Split(trimmedOutput, "\n")
|
||||||
|
|
||||||
return slices.FilterMap(outputLines, func(line string) (*models.Branch, bool) {
|
return lo.FilterMap(outputLines, func(line string, _ int) (*models.Branch, bool) {
|
||||||
if line == "" {
|
if line == "" {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@@ -138,7 +146,8 @@ func (self *BranchLoader) obtainBranches() []*models.Branch {
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return obtainBranch(split), true
|
storeCommitDateAsRecency := self.AppState.LocalBranchSortOrder != "recency"
|
||||||
|
return obtainBranch(split, storeCommitDateAsRecency), true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +159,18 @@ func (self *BranchLoader) getRawBranches() (string, error) {
|
|||||||
"%00",
|
"%00",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var sortOrder string
|
||||||
|
switch strings.ToLower(self.AppState.LocalBranchSortOrder) {
|
||||||
|
case "recency", "date":
|
||||||
|
sortOrder = "-committerdate"
|
||||||
|
case "alphabetical":
|
||||||
|
sortOrder = "refname"
|
||||||
|
default:
|
||||||
|
sortOrder = "refname"
|
||||||
|
}
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("for-each-ref").
|
cmdArgs := NewGitCmd("for-each-ref").
|
||||||
Arg("--sort=-committerdate").
|
Arg(fmt.Sprintf("--sort=%s", sortOrder)).
|
||||||
Arg(fmt.Sprintf("--format=%s", format)).
|
Arg(fmt.Sprintf("--format=%s", format)).
|
||||||
Arg("refs/heads").
|
Arg("refs/heads").
|
||||||
ToArgv()
|
ToArgv()
|
||||||
@@ -165,23 +184,33 @@ var branchFields = []string{
|
|||||||
"upstream:short",
|
"upstream:short",
|
||||||
"upstream:track",
|
"upstream:track",
|
||||||
"subject",
|
"subject",
|
||||||
fmt.Sprintf("objectname:short=%d", utils.COMMIT_HASH_SHORT_SIZE),
|
"objectname",
|
||||||
|
"committerdate:unix",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain branch information from parsed line output of getRawBranches()
|
// Obtain branch information from parsed line output of getRawBranches()
|
||||||
func obtainBranch(split []string) *models.Branch {
|
func obtainBranch(split []string, storeCommitDateAsRecency bool) *models.Branch {
|
||||||
headMarker := split[0]
|
headMarker := split[0]
|
||||||
fullName := split[1]
|
fullName := split[1]
|
||||||
upstreamName := split[2]
|
upstreamName := split[2]
|
||||||
track := split[3]
|
track := split[3]
|
||||||
subject := split[4]
|
subject := split[4]
|
||||||
commitHash := split[5]
|
commitHash := split[5]
|
||||||
|
commitDate := split[6]
|
||||||
|
|
||||||
name := strings.TrimPrefix(fullName, "heads/")
|
name := strings.TrimPrefix(fullName, "heads/")
|
||||||
pushables, pullables, gone := parseUpstreamInfo(upstreamName, track)
|
pushables, pullables, gone := parseUpstreamInfo(upstreamName, track)
|
||||||
|
|
||||||
|
recency := ""
|
||||||
|
if storeCommitDateAsRecency {
|
||||||
|
if unixTimestamp, err := strconv.ParseInt(commitDate, 10, 64); err == nil {
|
||||||
|
recency = utils.UnixToTimeAgo(unixTimestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &models.Branch{
|
return &models.Branch{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Recency: recency,
|
||||||
Pushables: pushables,
|
Pushables: pushables,
|
||||||
Pullables: pullables,
|
Pullables: pullables,
|
||||||
UpstreamGone: gone,
|
UpstreamGone: gone,
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package git_commands
|
|||||||
|
|
||||||
// "*|feat/detect-purge|origin/feat/detect-purge|[ahead 1]"
|
// "*|feat/detect-purge|origin/feat/detect-purge|[ahead 1]"
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -10,15 +12,21 @@ import (
|
|||||||
|
|
||||||
func TestObtainBranch(t *testing.T) {
|
func TestObtainBranch(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
input []string
|
input []string
|
||||||
expectedBranch *models.Branch
|
storeCommitDateAsRecency bool
|
||||||
|
expectedBranch *models.Branch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use a time stamp of 2 1/2 hours ago, resulting in a recency string of "2h"
|
||||||
|
now := time.Now().Unix()
|
||||||
|
timeStamp := strconv.Itoa(int(now - 2.5*60*60))
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
testName: "TrimHeads",
|
testName: "TrimHeads",
|
||||||
input: []string{"", "heads/a_branch", "", "", "subject", "123"},
|
input: []string{"", "heads/a_branch", "", "", "subject", "123", timeStamp},
|
||||||
|
storeCommitDateAsRecency: false,
|
||||||
expectedBranch: &models.Branch{
|
expectedBranch: &models.Branch{
|
||||||
Name: "a_branch",
|
Name: "a_branch",
|
||||||
Pushables: "?",
|
Pushables: "?",
|
||||||
@@ -29,8 +37,9 @@ func TestObtainBranch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "NoUpstream",
|
testName: "NoUpstream",
|
||||||
input: []string{"", "a_branch", "", "", "subject", "123"},
|
input: []string{"", "a_branch", "", "", "subject", "123", timeStamp},
|
||||||
|
storeCommitDateAsRecency: false,
|
||||||
expectedBranch: &models.Branch{
|
expectedBranch: &models.Branch{
|
||||||
Name: "a_branch",
|
Name: "a_branch",
|
||||||
Pushables: "?",
|
Pushables: "?",
|
||||||
@@ -41,8 +50,9 @@ func TestObtainBranch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "IsHead",
|
testName: "IsHead",
|
||||||
input: []string{"*", "a_branch", "", "", "subject", "123"},
|
input: []string{"*", "a_branch", "", "", "subject", "123", timeStamp},
|
||||||
|
storeCommitDateAsRecency: false,
|
||||||
expectedBranch: &models.Branch{
|
expectedBranch: &models.Branch{
|
||||||
Name: "a_branch",
|
Name: "a_branch",
|
||||||
Pushables: "?",
|
Pushables: "?",
|
||||||
@@ -53,8 +63,9 @@ func TestObtainBranch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "IsBehindAndAhead",
|
testName: "IsBehindAndAhead",
|
||||||
input: []string{"", "a_branch", "a_remote/a_branch", "[behind 2, ahead 3]", "subject", "123"},
|
input: []string{"", "a_branch", "a_remote/a_branch", "[behind 2, ahead 3]", "subject", "123", timeStamp},
|
||||||
|
storeCommitDateAsRecency: false,
|
||||||
expectedBranch: &models.Branch{
|
expectedBranch: &models.Branch{
|
||||||
Name: "a_branch",
|
Name: "a_branch",
|
||||||
Pushables: "3",
|
Pushables: "3",
|
||||||
@@ -65,8 +76,9 @@ func TestObtainBranch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "RemoteBranchIsGone",
|
testName: "RemoteBranchIsGone",
|
||||||
input: []string{"", "a_branch", "a_remote/a_branch", "[gone]", "subject", "123"},
|
input: []string{"", "a_branch", "a_remote/a_branch", "[gone]", "subject", "123", timeStamp},
|
||||||
|
storeCommitDateAsRecency: false,
|
||||||
expectedBranch: &models.Branch{
|
expectedBranch: &models.Branch{
|
||||||
Name: "a_branch",
|
Name: "a_branch",
|
||||||
UpstreamGone: true,
|
UpstreamGone: true,
|
||||||
@@ -77,11 +89,25 @@ func TestObtainBranch(t *testing.T) {
|
|||||||
CommitHash: "123",
|
CommitHash: "123",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
testName: "WithCommitDateAsRecency",
|
||||||
|
input: []string{"", "a_branch", "", "", "subject", "123", timeStamp},
|
||||||
|
storeCommitDateAsRecency: true,
|
||||||
|
expectedBranch: &models.Branch{
|
||||||
|
Name: "a_branch",
|
||||||
|
Recency: "2h",
|
||||||
|
Pushables: "?",
|
||||||
|
Pullables: "?",
|
||||||
|
Head: false,
|
||||||
|
Subject: "subject",
|
||||||
|
CommitHash: "123",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
branch := obtainBranch(s.input)
|
branch := obtainBranch(s.input, s.storeCommitDateAsRecency)
|
||||||
assert.EqualValues(t, s.expectedBranch, branch)
|
assert.EqualValues(t, s.expectedBranch, branch)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func TestBranchDeleteBranch(t *testing.T) {
|
|||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
instance := buildBranchCommands(commonDeps{runner: s.runner})
|
instance := buildBranchCommands(commonDeps{runner: s.runner})
|
||||||
|
|
||||||
s.test(instance.Delete("test", s.force))
|
s.test(instance.LocalDelete("test", s.force))
|
||||||
s.runner.CheckForMissingCalls()
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,22 @@ func (self *CommitCommands) SetAuthor(value string) error {
|
|||||||
return self.cmd.New(cmdArgs).Run()
|
return self.cmd.New(cmdArgs).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a commit's coauthor using Github/Gitlab Co-authored-by metadata. Value is expected to be of the form 'Name <Email>'
|
||||||
|
func (self *CommitCommands) AddCoAuthor(sha string, value string) error {
|
||||||
|
message, err := self.GetCommitMessage(sha)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
message = message + fmt.Sprintf("\nCo-authored-by: %s", value)
|
||||||
|
|
||||||
|
cmdArgs := NewGitCmd("commit").
|
||||||
|
Arg("--allow-empty", "--amend", "--only", "-m", message).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).Run()
|
||||||
|
}
|
||||||
|
|
||||||
// ResetToCommit reset to commit
|
// ResetToCommit reset to commit
|
||||||
func (self *CommitCommands) ResetToCommit(sha string, strength string, envVars []string) error {
|
func (self *CommitCommands) ResetToCommit(sha string, strength string, envVars []string) error {
|
||||||
cmdArgs := NewGitCmd("reset").Arg("--"+strength, sha).ToArgv()
|
cmdArgs := NewGitCmd("reset").Arg("--"+strength, sha).ToArgv()
|
||||||
@@ -50,13 +66,13 @@ func (self *CommitCommands) ResetToCommit(sha string, strength string, envVars [
|
|||||||
Run()
|
Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) CommitCmdObj(message string) oscommands.ICmdObj {
|
func (self *CommitCommands) CommitCmdObj(summary string, description string) oscommands.ICmdObj {
|
||||||
messageArgs := self.commitMessageArgs(message)
|
messageArgs := self.commitMessageArgs(summary, description)
|
||||||
|
|
||||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("commit").
|
cmdArgs := NewGitCmd("commit").
|
||||||
ArgIf(skipHookPrefix != "" && strings.HasPrefix(message, skipHookPrefix), "--no-verify").
|
ArgIf(skipHookPrefix != "" && strings.HasPrefix(summary, skipHookPrefix), "--no-verify").
|
||||||
ArgIf(self.signoffFlag() != "", self.signoffFlag()).
|
ArgIf(self.signoffFlag() != "", self.signoffFlag()).
|
||||||
Arg(messageArgs...).
|
Arg(messageArgs...).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
@@ -68,9 +84,22 @@ func (self *CommitCommands) RewordLastCommitInEditorCmdObj() oscommands.ICmdObj
|
|||||||
return self.cmd.New(NewGitCmd("commit").Arg("--allow-empty", "--amend", "--only").ToArgv())
|
return self.cmd.New(NewGitCmd("commit").Arg("--allow-empty", "--amend", "--only").ToArgv())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitCommands) RewordLastCommitInEditorWithMessageFileCmdObj(tmpMessageFile string) oscommands.ICmdObj {
|
||||||
|
return self.cmd.New(NewGitCmd("commit").
|
||||||
|
Arg("--allow-empty", "--amend", "--only", "--edit", "--file="+tmpMessageFile).ToArgv())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitCommands) CommitInEditorWithMessageFileCmdObj(tmpMessageFile string) oscommands.ICmdObj {
|
||||||
|
return self.cmd.New(NewGitCmd("commit").
|
||||||
|
Arg("--edit").
|
||||||
|
Arg("--file="+tmpMessageFile).
|
||||||
|
ArgIf(self.signoffFlag() != "", self.signoffFlag()).
|
||||||
|
ToArgv())
|
||||||
|
}
|
||||||
|
|
||||||
// RewordLastCommit rewords the topmost commit with the given message
|
// RewordLastCommit rewords the topmost commit with the given message
|
||||||
func (self *CommitCommands) RewordLastCommit(message string) error {
|
func (self *CommitCommands) RewordLastCommit(summary string, description string) error {
|
||||||
messageArgs := self.commitMessageArgs(message)
|
messageArgs := self.commitMessageArgs(summary, description)
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("commit").
|
cmdArgs := NewGitCmd("commit").
|
||||||
Arg("--allow-empty", "--amend", "--only").
|
Arg("--allow-empty", "--amend", "--only").
|
||||||
@@ -80,9 +109,8 @@ func (self *CommitCommands) RewordLastCommit(message string) error {
|
|||||||
return self.cmd.New(cmdArgs).Run()
|
return self.cmd.New(cmdArgs).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) commitMessageArgs(message string) []string {
|
func (self *CommitCommands) commitMessageArgs(summary string, description string) []string {
|
||||||
msg, description, _ := strings.Cut(message, "\n")
|
args := []string{"-m", summary}
|
||||||
args := []string{"-m", msg}
|
|
||||||
|
|
||||||
if description != "" {
|
if description != "" {
|
||||||
args = append(args, "-m", description)
|
args = append(args, "-m", description)
|
||||||
@@ -108,22 +136,22 @@ func (self *CommitCommands) signoffFlag() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the subject of the HEAD commit
|
func (self *CommitCommands) GetCommitMessage(commitSha string) (string, error) {
|
||||||
func (self *CommitCommands) GetHeadCommitMessage() (string, error) {
|
cmdArgs := NewGitCmd("log").
|
||||||
cmdArgs := NewGitCmd("log").Arg("-1", "--pretty=%s").ToArgv()
|
Arg("--format=%B", "--max-count=1", commitSha).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
message, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
message, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
return strings.TrimSpace(message), err
|
return strings.TrimSpace(message), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) GetCommitMessage(commitSha string) (string, error) {
|
func (self *CommitCommands) GetCommitSubject(commitSha string) (string, error) {
|
||||||
cmdArgs := NewGitCmd("rev-list").
|
cmdArgs := NewGitCmd("log").
|
||||||
Arg("--format=%B", "--max-count=1", commitSha).
|
Arg("--format=%s", "--max-count=1", commitSha).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
messageWithHeader, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
subject, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
message := strings.Join(strings.SplitAfter(messageWithHeader, "\n")[1:], "")
|
return strings.TrimSpace(subject), err
|
||||||
return strings.TrimSpace(message), err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) GetCommitDiff(commitSha string) (string, error) {
|
func (self *CommitCommands) GetCommitDiff(commitSha string) (string, error) {
|
||||||
@@ -170,6 +198,20 @@ func (self *CommitCommands) GetCommitMessagesFirstLine(shas []string) (string, e
|
|||||||
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Example output:
|
||||||
|
//
|
||||||
|
// cd50c79ae Preserve the commit message correctly even if the description has blank lines
|
||||||
|
// 3ebba5f32 Add test demonstrating a bug with preserving the commit message
|
||||||
|
// 9a423c388 Remove unused function
|
||||||
|
func (self *CommitCommands) GetShasAndCommitMessagesFirstLine(shas []string) (string, error) {
|
||||||
|
cmdArgs := NewGitCmd("show").
|
||||||
|
Arg("--no-patch", "--pretty=format:%h %s").
|
||||||
|
Arg(shas...).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) GetCommitsOneline(shas []string) (string, error) {
|
func (self *CommitCommands) GetCommitsOneline(shas []string) (string, error) {
|
||||||
cmdArgs := NewGitCmd("show").
|
cmdArgs := NewGitCmd("show").
|
||||||
Arg("--no-patch", "--oneline").
|
Arg("--no-patch", "--oneline").
|
||||||
@@ -192,10 +234,13 @@ func (self *CommitCommands) AmendHeadCmdObj() oscommands.ICmdObj {
|
|||||||
return self.cmd.New(cmdArgs)
|
return self.cmd.New(cmdArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) ShowCmdObj(sha string, filterPath string, ignoreWhitespace bool) oscommands.ICmdObj {
|
func (self *CommitCommands) ShowCmdObj(sha string, filterPath string) oscommands.ICmdObj {
|
||||||
contextSize := self.UserConfig.Git.DiffContextSize
|
contextSize := self.AppState.DiffContextSize
|
||||||
|
|
||||||
|
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||||
cmdArgs := NewGitCmd("show").
|
cmdArgs := NewGitCmd("show").
|
||||||
|
ConfigIf(extDiffCmd != "", "diff.external="+extDiffCmd).
|
||||||
|
ArgIfElse(extDiffCmd != "", "--ext-diff", "--no-ext-diff").
|
||||||
Arg("--submodule").
|
Arg("--submodule").
|
||||||
Arg("--color="+self.UserConfig.Git.Paging.ColorArg).
|
Arg("--color="+self.UserConfig.Git.Paging.ColorArg).
|
||||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||||
@@ -203,8 +248,9 @@ func (self *CommitCommands) ShowCmdObj(sha string, filterPath string, ignoreWhit
|
|||||||
Arg("--decorate").
|
Arg("--decorate").
|
||||||
Arg("-p").
|
Arg("-p").
|
||||||
Arg(sha).
|
Arg(sha).
|
||||||
ArgIf(ignoreWhitespace, "--ignore-all-space").
|
ArgIf(self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||||
ArgIf(filterPath != "", "--", filterPath).
|
ArgIf(filterPath != "", "--", filterPath).
|
||||||
|
Dir(self.repoPaths.worktreePath).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package git_commands
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
@@ -52,7 +51,7 @@ func getCommitFilesFromFilenames(filenames string) []*models.CommitFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// typical result looks like 'A my_file' meaning my_file was added
|
// typical result looks like 'A my_file' meaning my_file was added
|
||||||
return slices.Map(lo.Chunk(lines, 2), func(chunk []string) *models.CommitFile {
|
return lo.Map(lo.Chunk(lines, 2), func(chunk []string, _ int) *models.CommitFile {
|
||||||
return &models.CommitFile{
|
return &models.CommitFile{
|
||||||
ChangeStatus: chunk[0],
|
ChangeStatus: chunk[0],
|
||||||
Name: chunk[1],
|
Name: chunk[1],
|
||||||
|
|||||||
@@ -6,15 +6,17 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,7 +47,6 @@ type CommitLoader struct {
|
|||||||
func NewCommitLoader(
|
func NewCommitLoader(
|
||||||
cmn *common.Common,
|
cmn *common.Common,
|
||||||
cmd oscommands.ICmdObjBuilder,
|
cmd oscommands.ICmdObjBuilder,
|
||||||
dotGitDir string,
|
|
||||||
getRebaseMode func() (enums.RebaseMode, error),
|
getRebaseMode func() (enums.RebaseMode, error),
|
||||||
gitCommon *GitCommon,
|
gitCommon *GitCommon,
|
||||||
) *CommitLoader {
|
) *CommitLoader {
|
||||||
@@ -55,7 +56,6 @@ func NewCommitLoader(
|
|||||||
getRebaseMode: getRebaseMode,
|
getRebaseMode: getRebaseMode,
|
||||||
readFile: os.ReadFile,
|
readFile: os.ReadFile,
|
||||||
walkFiles: filepath.Walk,
|
walkFiles: filepath.Walk,
|
||||||
dotGitDir: dotGitDir,
|
|
||||||
mainBranches: nil,
|
mainBranches: nil,
|
||||||
GitCommon: gitCommon,
|
GitCommon: gitCommon,
|
||||||
}
|
}
|
||||||
@@ -66,8 +66,11 @@ type GetCommitsOptions struct {
|
|||||||
FilterPath string
|
FilterPath string
|
||||||
IncludeRebaseCommits bool
|
IncludeRebaseCommits bool
|
||||||
RefName string // e.g. "HEAD" or "my_branch"
|
RefName string // e.g. "HEAD" or "my_branch"
|
||||||
|
RefForPushedStatus string // the ref to use for determining pushed/unpushed status
|
||||||
// determines if we show the whole git graph i.e. pass the '--all' flag
|
// determines if we show the whole git graph i.e. pass the '--all' flag
|
||||||
All bool
|
All bool
|
||||||
|
// If non-empty, show divergence from this ref (left-right log)
|
||||||
|
RefToShowDivergenceFrom string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommits obtains the commits of the current branch
|
// GetCommits obtains the commits of the current branch
|
||||||
@@ -84,31 +87,81 @@ func (self *CommitLoader) GetCommits(opts GetCommitsOptions) ([]*models.Commit,
|
|||||||
commits = append(commits, rebasingCommits...)
|
commits = append(commits, rebasingCommits...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
|
wg.Add(2)
|
||||||
|
|
||||||
|
var logErr error
|
||||||
|
go utils.Safe(func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
logErr = self.getLogCmd(opts).RunAndProcessLines(func(line string) (bool, error) {
|
||||||
|
commit := self.extractCommitFromLine(line, opts.RefToShowDivergenceFrom != "")
|
||||||
|
commits = append(commits, commit)
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
var ancestor string
|
||||||
|
var remoteAncestor string
|
||||||
|
go utils.Safe(func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
ancestor = self.getMergeBase(opts.RefName)
|
||||||
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
|
remoteAncestor = self.getMergeBase(opts.RefToShowDivergenceFrom)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
passedFirstPushedCommit := false
|
passedFirstPushedCommit := false
|
||||||
firstPushedCommit, err := self.getFirstPushedCommit(opts.RefName)
|
// I can get this before
|
||||||
|
firstPushedCommit, err := self.getFirstPushedCommit(opts.RefForPushedStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// must have no upstream branch so we'll consider everything as pushed
|
// must have no upstream branch so we'll consider everything as pushed
|
||||||
passedFirstPushedCommit = true
|
passedFirstPushedCommit = true
|
||||||
}
|
}
|
||||||
|
|
||||||
err = self.getLogCmd(opts).RunAndProcessLines(func(line string) (bool, error) {
|
wg.Wait()
|
||||||
commit := self.extractCommitFromLine(line)
|
|
||||||
|
if logErr != nil {
|
||||||
|
return nil, logErr
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, commit := range commits {
|
||||||
if commit.Sha == firstPushedCommit {
|
if commit.Sha == firstPushedCommit {
|
||||||
passedFirstPushedCommit = true
|
passedFirstPushedCommit = true
|
||||||
}
|
}
|
||||||
commit.Status = map[bool]models.CommitStatus{true: models.StatusUnpushed, false: models.StatusPushed}[!passedFirstPushedCommit]
|
if commit.Status != models.StatusRebasing {
|
||||||
commits = append(commits, commit)
|
if passedFirstPushedCommit {
|
||||||
return false, nil
|
commit.Status = models.StatusPushed
|
||||||
})
|
} else {
|
||||||
if err != nil {
|
commit.Status = models.StatusUnpushed
|
||||||
return nil, err
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(commits) == 0 {
|
if len(commits) == 0 {
|
||||||
return commits, nil
|
return commits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
commits = self.setCommitMergedStatuses(opts.RefName, commits)
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
|
sort.SliceStable(commits, func(i, j int) bool {
|
||||||
|
// In the divergence view we want incoming commits to come first
|
||||||
|
return commits[i].Divergence > commits[j].Divergence
|
||||||
|
})
|
||||||
|
|
||||||
|
_, localSectionStart, found := lo.FindIndexOf(commits, func(commit *models.Commit) bool {
|
||||||
|
return commit.Divergence == models.DivergenceLeft
|
||||||
|
})
|
||||||
|
if !found {
|
||||||
|
localSectionStart = len(commits)
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommitMergedStatuses(remoteAncestor, commits[:localSectionStart])
|
||||||
|
setCommitMergedStatuses(ancestor, commits[localSectionStart:])
|
||||||
|
} else {
|
||||||
|
setCommitMergedStatuses(ancestor, commits)
|
||||||
|
}
|
||||||
|
|
||||||
return commits, nil
|
return commits, nil
|
||||||
}
|
}
|
||||||
@@ -148,8 +201,8 @@ func (self *CommitLoader) MergeRebasingCommits(commits []*models.Commit) ([]*mod
|
|||||||
// then puts them into a commit object
|
// then puts them into a commit object
|
||||||
// example input:
|
// example input:
|
||||||
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
|
// 8ad01fe32fcc20f07bc6693f87aa4977c327f1e1|10 hours ago|Jesse Duffield| (HEAD -> master, tag: v0.15.2)|refresh commits when adding a tag
|
||||||
func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit {
|
func (self *CommitLoader) extractCommitFromLine(line string, showDivergence bool) *models.Commit {
|
||||||
split := strings.SplitN(line, "\x00", 7)
|
split := strings.SplitN(line, "\x00", 8)
|
||||||
|
|
||||||
sha := split[0]
|
sha := split[0]
|
||||||
unixTimestamp := split[1]
|
unixTimestamp := split[1]
|
||||||
@@ -158,6 +211,10 @@ func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit {
|
|||||||
extraInfo := strings.TrimSpace(split[4])
|
extraInfo := strings.TrimSpace(split[4])
|
||||||
parentHashes := split[5]
|
parentHashes := split[5]
|
||||||
message := split[6]
|
message := split[6]
|
||||||
|
divergence := models.DivergenceNone
|
||||||
|
if showDivergence {
|
||||||
|
divergence = lo.Ternary(split[7] == "<", models.DivergenceLeft, models.DivergenceRight)
|
||||||
|
}
|
||||||
|
|
||||||
tags := []string{}
|
tags := []string{}
|
||||||
|
|
||||||
@@ -191,6 +248,7 @@ func (self *CommitLoader) extractCommitFromLine(line string) *models.Commit {
|
|||||||
AuthorName: authorName,
|
AuthorName: authorName,
|
||||||
AuthorEmail: authorEmail,
|
AuthorEmail: authorEmail,
|
||||||
Parents: parents,
|
Parents: parents,
|
||||||
|
Divergence: divergence,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +262,7 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
commitShas := slices.FilterMap(commits, func(commit *models.Commit) (string, bool) {
|
commitShas := lo.FilterMap(commits, func(commit *models.Commit, _ int) (string, bool) {
|
||||||
return commit.Sha, commit.Sha != ""
|
return commit.Sha, commit.Sha != ""
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -220,7 +278,7 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
|
|||||||
|
|
||||||
fullCommits := map[string]*models.Commit{}
|
fullCommits := map[string]*models.Commit{}
|
||||||
err = cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
err = cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
||||||
commit := self.extractCommitFromLine(line)
|
commit := self.extractCommitFromLine(line, false)
|
||||||
fullCommits[commit.Sha] = commit
|
fullCommits[commit.Sha] = commit
|
||||||
return false, nil
|
return false, nil
|
||||||
})
|
})
|
||||||
@@ -268,7 +326,7 @@ func (self *CommitLoader) getRebasingCommits(rebaseMode enums.RebaseMode) ([]*mo
|
|||||||
|
|
||||||
func (self *CommitLoader) getNormalRebasingCommits() ([]*models.Commit, error) {
|
func (self *CommitLoader) getNormalRebasingCommits() ([]*models.Commit, error) {
|
||||||
rewrittenCount := 0
|
rewrittenCount := 0
|
||||||
bytesContent, err := self.readFile(filepath.Join(self.dotGitDir, "rebase-apply/rewritten"))
|
bytesContent, err := self.readFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply/rewritten"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
content := string(bytesContent)
|
content := string(bytesContent)
|
||||||
rewrittenCount = len(strings.Split(content, "\n"))
|
rewrittenCount = len(strings.Split(content, "\n"))
|
||||||
@@ -276,7 +334,7 @@ func (self *CommitLoader) getNormalRebasingCommits() ([]*models.Commit, error) {
|
|||||||
|
|
||||||
// we know we're rebasing, so lets get all the files whose names have numbers
|
// we know we're rebasing, so lets get all the files whose names have numbers
|
||||||
commits := []*models.Commit{}
|
commits := []*models.Commit{}
|
||||||
err = self.walkFiles(filepath.Join(self.dotGitDir, "rebase-apply"), func(path string, f os.FileInfo, err error) error {
|
err = self.walkFiles(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply"), func(path string, f os.FileInfo, err error) error {
|
||||||
if rewrittenCount > 0 {
|
if rewrittenCount > 0 {
|
||||||
rewrittenCount--
|
rewrittenCount--
|
||||||
return nil
|
return nil
|
||||||
@@ -317,7 +375,7 @@ func (self *CommitLoader) getNormalRebasingCommits() ([]*models.Commit, error) {
|
|||||||
// and extracts out the sha and names of commits that we still have to go
|
// and extracts out the sha and names of commits that we still have to go
|
||||||
// in the rebase:
|
// in the rebase:
|
||||||
func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, error) {
|
func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, error) {
|
||||||
bytesContent, err := self.readFile(filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo"))
|
bytesContent, err := self.readFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Error(fmt.Sprintf("error occurred reading git-rebase-todo: %s", err.Error()))
|
self.Log.Error(fmt.Sprintf("error occurred reading git-rebase-todo: %s", err.Error()))
|
||||||
// we assume an error means the file doesn't exist so we just return
|
// we assume an error means the file doesn't exist so we just return
|
||||||
@@ -350,7 +408,7 @@ func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, err
|
|||||||
// Command does not have a commit associated, skip
|
// Command does not have a commit associated, skip
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
commits = slices.Prepend(commits, &models.Commit{
|
commits = utils.Prepend(commits, &models.Commit{
|
||||||
Sha: t.Commit,
|
Sha: t.Commit,
|
||||||
Name: t.Msg,
|
Name: t.Msg,
|
||||||
Status: models.StatusRebasing,
|
Status: models.StatusRebasing,
|
||||||
@@ -362,7 +420,7 @@ func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitLoader) getConflictedCommit(todos []todo.Todo) string {
|
func (self *CommitLoader) getConflictedCommit(todos []todo.Todo) string {
|
||||||
bytesContent, err := self.readFile(filepath.Join(self.dotGitDir, "rebase-merge/done"))
|
bytesContent, err := self.readFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/done"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.Log.Error(fmt.Sprintf("error occurred reading rebase-merge/done: %s", err.Error()))
|
self.Log.Error(fmt.Sprintf("error occurred reading rebase-merge/done: %s", err.Error()))
|
||||||
return ""
|
return ""
|
||||||
@@ -375,7 +433,7 @@ func (self *CommitLoader) getConflictedCommit(todos []todo.Todo) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
amendFileExists := false
|
amendFileExists := false
|
||||||
if _, err := os.Stat(filepath.Join(self.dotGitDir, "rebase-merge/amend")); err == nil {
|
if _, err := os.Stat(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/amend")); err == nil {
|
||||||
amendFileExists = true
|
amendFileExists = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,14 +522,15 @@ func (self *CommitLoader) commitFromPatch(content string) *models.Commit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitLoader) setCommitMergedStatuses(refName string, commits []*models.Commit) []*models.Commit {
|
func setCommitMergedStatuses(ancestor string, commits []*models.Commit) {
|
||||||
ancestor := self.getMergeBase(refName)
|
|
||||||
if ancestor == "" {
|
if ancestor == "" {
|
||||||
return commits
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
passedAncestor := false
|
passedAncestor := false
|
||||||
for i, commit := range commits {
|
for i, commit := range commits {
|
||||||
if strings.HasPrefix(ancestor, commit.Sha) {
|
// some commits aren't really commits and don't have sha's, such as the update-ref todo
|
||||||
|
if commit.Sha != "" && strings.HasPrefix(ancestor, commit.Sha) {
|
||||||
passedAncestor = true
|
passedAncestor = true
|
||||||
}
|
}
|
||||||
if commit.Status != models.StatusPushed && commit.Status != models.StatusUnpushed {
|
if commit.Status != models.StatusPushed && commit.Status != models.StatusUnpushed {
|
||||||
@@ -481,7 +540,6 @@ func (self *CommitLoader) setCommitMergedStatuses(refName string, commits []*mod
|
|||||||
commits[i].Status = models.StatusMerged
|
commits[i].Status = models.StatusMerged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return commits
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitLoader) getMergeBase(refName string) string {
|
func (self *CommitLoader) getMergeBase(refName string) string {
|
||||||
@@ -510,13 +568,25 @@ func (self *CommitLoader) getMergeBase(refName string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitLoader) getExistingMainBranches() []string {
|
func (self *CommitLoader) getExistingMainBranches() []string {
|
||||||
return lo.FilterMap(self.UserConfig.Git.MainBranches,
|
var existingBranches []string
|
||||||
func(branchName string, _ int) (string, bool) {
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
mainBranches := self.UserConfig.Git.MainBranches
|
||||||
|
existingBranches = make([]string, len(mainBranches))
|
||||||
|
|
||||||
|
for i, branchName := range mainBranches {
|
||||||
|
wg.Add(1)
|
||||||
|
i := i
|
||||||
|
branchName := branchName
|
||||||
|
go utils.Safe(func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
// Try to determine upstream of local main branch
|
// Try to determine upstream of local main branch
|
||||||
if ref, err := self.cmd.New(
|
if ref, err := self.cmd.New(
|
||||||
NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(),
|
NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(),
|
||||||
).DontLog().RunWithOutput(); err == nil {
|
).DontLog().RunWithOutput(); err == nil {
|
||||||
return strings.TrimSpace(ref), true
|
existingBranches[i] = strings.TrimSpace(ref)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this failed, a local branch for this main branch doesn't exist or it
|
// If this failed, a local branch for this main branch doesn't exist or it
|
||||||
@@ -525,7 +595,8 @@ func (self *CommitLoader) getExistingMainBranches() []string {
|
|||||||
if err := self.cmd.New(
|
if err := self.cmd.New(
|
||||||
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
||||||
).DontLog().Run(); err == nil {
|
).DontLog().Run(); err == nil {
|
||||||
return ref, true
|
existingBranches[i] = ref
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this failed as well, try if we have the main branch as a local
|
// If this failed as well, try if we have the main branch as a local
|
||||||
@@ -535,11 +606,18 @@ func (self *CommitLoader) getExistingMainBranches() []string {
|
|||||||
if err := self.cmd.New(
|
if err := self.cmd.New(
|
||||||
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(),
|
||||||
).DontLog().Run(); err == nil {
|
).DontLog().Run(); err == nil {
|
||||||
return ref, true
|
existingBranches[i] = ref
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", false
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
existingBranches = lo.Filter(existingBranches, func(branch string, _ int) bool {
|
||||||
|
return branch != ""
|
||||||
|
})
|
||||||
|
|
||||||
|
return existingBranches
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignoringWarnings(commandOutput string) string {
|
func ignoringWarnings(commandOutput string) string {
|
||||||
@@ -574,8 +652,13 @@ func (self *CommitLoader) getFirstPushedCommit(refName string) (string, error) {
|
|||||||
func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
||||||
config := self.UserConfig.Git.Log
|
config := self.UserConfig.Git.Log
|
||||||
|
|
||||||
|
refSpec := opts.RefName
|
||||||
|
if opts.RefToShowDivergenceFrom != "" {
|
||||||
|
refSpec += "..." + opts.RefToShowDivergenceFrom
|
||||||
|
}
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("log").
|
cmdArgs := NewGitCmd("log").
|
||||||
Arg(opts.RefName).
|
Arg(refSpec).
|
||||||
ArgIf(config.Order != "default", "--"+config.Order).
|
ArgIf(config.Order != "default", "--"+config.Order).
|
||||||
ArgIf(opts.All, "--all").
|
ArgIf(opts.All, "--all").
|
||||||
Arg("--oneline").
|
Arg("--oneline").
|
||||||
@@ -584,6 +667,7 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
|||||||
ArgIf(opts.Limit, "-300").
|
ArgIf(opts.Limit, "-300").
|
||||||
ArgIf(opts.FilterPath != "", "--follow").
|
ArgIf(opts.FilterPath != "", "--follow").
|
||||||
Arg("--no-show-signature").
|
Arg("--no-show-signature").
|
||||||
|
ArgIf(opts.RefToShowDivergenceFrom != "", "--left-right").
|
||||||
Arg("--").
|
Arg("--").
|
||||||
ArgIf(opts.FilterPath != "", opts.FilterPath).
|
ArgIf(opts.FilterPath != "", opts.FilterPath).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
@@ -591,4 +675,4 @@ func (self *CommitLoader) getLogCmd(opts GetCommitsOptions) oscommands.ICmdObj {
|
|||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
}
|
}
|
||||||
|
|
||||||
const prettyFormat = `--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s`
|
const prettyFormat = `--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m`
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package git_commands
|
package git_commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||||
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
@@ -42,10 +42,10 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should return no commits if there are none",
|
testName: "should return no commits if there are none",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@@ -54,10 +54,10 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should use proper upstream name for branch",
|
testName: "should use proper upstream name for branch",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "refs/heads/mybranch", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "refs/heads/mybranch", RefForPushedStatus: "refs/heads/mybranch", IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "refs/heads/mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "refs/heads/mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "refs/heads/mybranch", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "refs/heads/mybranch", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@@ -66,13 +66,13 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should return commits if they are present",
|
testName: "should return commits if they are present",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
mainBranches: []string{"master", "main", "develop"},
|
mainBranches: []string{"master", "main", "develop"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
// here it's seeing which commits are yet to be pushed
|
// here it's seeing which commits are yet to be pushed
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
// here it's actually getting all the commits in a formatted form, one per line
|
// here it's actually getting all the commits in a formatted form, one per line
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, commitsOutput, nil).
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, commitsOutput, nil).
|
||||||
// here it's testing which of the configured main branches have an upstream
|
// here it's testing which of the configured main branches have an upstream
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil). // this one does
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil). // this one does
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead
|
||||||
@@ -203,13 +203,13 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should not call merge-base for mainBranches if none exist",
|
testName: "should not call merge-base for mainBranches if none exist",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
mainBranches: []string{"master", "main"},
|
mainBranches: []string{"master", "main"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
// here it's seeing which commits are yet to be pushed
|
// here it's seeing which commits are yet to be pushed
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
// here it's actually getting all the commits in a formatted form, one per line
|
// here it's actually getting all the commits in a formatted form, one per line
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
||||||
// here it's testing which of the configured main branches exist; neither does
|
// here it's testing which of the configured main branches exist; neither does
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "", errors.New("error")).
|
||||||
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/master"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/master"}, "", errors.New("error")).
|
||||||
@@ -240,13 +240,13 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should call merge-base for all main branches that exist",
|
testName: "should call merge-base for all main branches that exist",
|
||||||
logOrder: "topo-order",
|
logOrder: "topo-order",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
mainBranches: []string{"master", "main", "develop", "1.0-hotfixes"},
|
mainBranches: []string{"master", "main", "develop", "1.0-hotfixes"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
// here it's seeing which commits are yet to be pushed
|
// here it's seeing which commits are yet to be pushed
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
// here it's actually getting all the commits in a formatted form, one per line
|
// here it's actually getting all the commits in a formatted form, one per line
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil).
|
||||||
// here it's testing which of the configured main branches exist
|
// here it's testing which of the configured main branches exist
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil).
|
||||||
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")).
|
ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")).
|
||||||
@@ -279,10 +279,10 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should not specify order if `log.order` is `default`",
|
testName: "should not specify order if `log.order` is `default`",
|
||||||
logOrder: "default",
|
logOrder: "default",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", IncludeRebaseCommits: false},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--no-show-signature", "--"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@@ -291,10 +291,10 @@ func TestGetCommits(t *testing.T) {
|
|||||||
testName: "should set filter path",
|
testName: "should set filter path",
|
||||||
logOrder: "default",
|
logOrder: "default",
|
||||||
rebaseMode: enums.REBASE_MODE_NONE,
|
rebaseMode: enums.REBASE_MODE_NONE,
|
||||||
opts: GetCommitsOptions{RefName: "HEAD", FilterPath: "src"},
|
opts: GetCommitsOptions{RefName: "HEAD", RefForPushedStatus: "mybranch", FilterPath: "src"},
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
ExpectGitArgs([]string{"merge-base", "mybranch", "mybranch@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil).
|
||||||
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s", "--abbrev=40", "--follow", "--no-show-signature", "--", "src"}, "", nil),
|
ExpectGitArgs([]string{"log", "HEAD", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%D%x00%p%x00%s%x00%m", "--abbrev=40", "--follow", "--no-show-signature", "--", "src"}, "", nil),
|
||||||
|
|
||||||
expectedCommits: []*models.Commit{},
|
expectedCommits: []*models.Commit{},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@@ -506,3 +506,51 @@ func TestCommitLoader_getConflictedCommitImpl(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
|
||||||
|
type scenario struct {
|
||||||
|
testName string
|
||||||
|
commits []*models.Commit
|
||||||
|
ancestor string
|
||||||
|
expectedCommits []*models.Commit
|
||||||
|
}
|
||||||
|
|
||||||
|
scenarios := []scenario{
|
||||||
|
{
|
||||||
|
testName: "basic",
|
||||||
|
commits: []*models.Commit{
|
||||||
|
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||||
|
{Sha: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusPushed},
|
||||||
|
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||||
|
},
|
||||||
|
ancestor: "67890",
|
||||||
|
expectedCommits: []*models.Commit{
|
||||||
|
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||||
|
{Sha: "67890", Name: "2", Action: models.ActionNone, Status: models.StatusMerged},
|
||||||
|
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusMerged},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "with update-ref",
|
||||||
|
commits: []*models.Commit{
|
||||||
|
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||||
|
{Sha: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||||
|
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||||
|
},
|
||||||
|
ancestor: "deadbeef",
|
||||||
|
expectedCommits: []*models.Commit{
|
||||||
|
{Sha: "12345", Name: "1", Action: models.ActionNone, Status: models.StatusUnpushed},
|
||||||
|
{Sha: "", Name: "", Action: todo.UpdateRef, Status: models.StatusNone},
|
||||||
|
{Sha: "abcde", Name: "3", Action: models.ActionNone, Status: models.StatusPushed},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
t.Run(scenario.testName, func(t *testing.T) {
|
||||||
|
expectedCommits := scenario.commits
|
||||||
|
setCommitMergedStatuses(scenario.ancestor, expectedCommits)
|
||||||
|
assert.Equal(t, scenario.expectedCommits, expectedCommits)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,20 +10,23 @@ import (
|
|||||||
|
|
||||||
func TestCommitRewordCommit(t *testing.T) {
|
func TestCommitRewordCommit(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
runner *oscommands.FakeCmdObjRunner
|
runner *oscommands.FakeCmdObjRunner
|
||||||
input string
|
summary string
|
||||||
|
description string
|
||||||
}
|
}
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"Single line reword",
|
"Single line reword",
|
||||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test"}, "", nil),
|
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test"}, "", nil),
|
||||||
"test",
|
"test",
|
||||||
|
"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Multi line reword",
|
"Multi line reword",
|
||||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test", "-m", "line 2\nline 3"}, "", nil),
|
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test", "-m", "line 2\nline 3"}, "", nil),
|
||||||
"test\nline 2\nline 3",
|
"test",
|
||||||
|
"line 2\nline 3",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
@@ -31,7 +34,7 @@ func TestCommitRewordCommit(t *testing.T) {
|
|||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
instance := buildCommitCommands(commonDeps{runner: s.runner})
|
instance := buildCommitCommands(commonDeps{runner: s.runner})
|
||||||
|
|
||||||
assert.NoError(t, instance.RewordLastCommit(s.input))
|
assert.NoError(t, instance.RewordLastCommit(s.summary, s.description))
|
||||||
s.runner.CheckForMissingCalls()
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -50,7 +53,8 @@ func TestCommitResetToCommit(t *testing.T) {
|
|||||||
func TestCommitCommitCmdObj(t *testing.T) {
|
func TestCommitCommitCmdObj(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
testName string
|
testName string
|
||||||
message string
|
summary string
|
||||||
|
description string
|
||||||
configSignoff bool
|
configSignoff bool
|
||||||
configSkipHookPrefix string
|
configSkipHookPrefix string
|
||||||
expectedArgs []string
|
expectedArgs []string
|
||||||
@@ -59,35 +63,36 @@ func TestCommitCommitCmdObj(t *testing.T) {
|
|||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
testName: "Commit",
|
testName: "Commit",
|
||||||
message: "test",
|
summary: "test",
|
||||||
configSignoff: false,
|
configSignoff: false,
|
||||||
configSkipHookPrefix: "",
|
configSkipHookPrefix: "",
|
||||||
expectedArgs: []string{"commit", "-m", "test"},
|
expectedArgs: []string{"commit", "-m", "test"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Commit with --no-verify flag",
|
testName: "Commit with --no-verify flag",
|
||||||
message: "WIP: test",
|
summary: "WIP: test",
|
||||||
configSignoff: false,
|
configSignoff: false,
|
||||||
configSkipHookPrefix: "WIP",
|
configSkipHookPrefix: "WIP",
|
||||||
expectedArgs: []string{"commit", "--no-verify", "-m", "WIP: test"},
|
expectedArgs: []string{"commit", "--no-verify", "-m", "WIP: test"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Commit with multiline message",
|
testName: "Commit with multiline message",
|
||||||
message: "line1\nline2",
|
summary: "line1",
|
||||||
|
description: "line2",
|
||||||
configSignoff: false,
|
configSignoff: false,
|
||||||
configSkipHookPrefix: "",
|
configSkipHookPrefix: "",
|
||||||
expectedArgs: []string{"commit", "-m", "line1", "-m", "line2"},
|
expectedArgs: []string{"commit", "-m", "line1", "-m", "line2"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Commit with signoff",
|
testName: "Commit with signoff",
|
||||||
message: "test",
|
summary: "test",
|
||||||
configSignoff: true,
|
configSignoff: true,
|
||||||
configSkipHookPrefix: "",
|
configSkipHookPrefix: "",
|
||||||
expectedArgs: []string{"commit", "--signoff", "-m", "test"},
|
expectedArgs: []string{"commit", "--signoff", "-m", "test"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Commit with signoff and no-verify",
|
testName: "Commit with signoff and no-verify",
|
||||||
message: "WIP: test",
|
summary: "WIP: test",
|
||||||
configSignoff: true,
|
configSignoff: true,
|
||||||
configSkipHookPrefix: "WIP",
|
configSkipHookPrefix: "WIP",
|
||||||
expectedArgs: []string{"commit", "--no-verify", "--signoff", "-m", "WIP: test"},
|
expectedArgs: []string{"commit", "--no-verify", "--signoff", "-m", "WIP: test"},
|
||||||
@@ -104,7 +109,7 @@ func TestCommitCommitCmdObj(t *testing.T) {
|
|||||||
runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expectedArgs, "", nil)
|
runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expectedArgs, "", nil)
|
||||||
instance := buildCommitCommands(commonDeps{userConfig: userConfig, runner: runner})
|
instance := buildCommitCommands(commonDeps{userConfig: userConfig, runner: runner})
|
||||||
|
|
||||||
assert.NoError(t, instance.CommitCmdObj(s.message).Run())
|
assert.NoError(t, instance.CommitCmdObj(s.summary, s.description).Run())
|
||||||
runner.CheckForMissingCalls()
|
runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -181,6 +186,7 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||||||
filterPath string
|
filterPath string
|
||||||
contextSize int
|
contextSize int
|
||||||
ignoreWhitespace bool
|
ignoreWhitespace bool
|
||||||
|
extDiffCmd string
|
||||||
expected []string
|
expected []string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,28 +196,40 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||||||
filterPath: "",
|
filterPath: "",
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
expected: []string{"show", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
|
extDiffCmd: "",
|
||||||
|
expected: []string{"-C", "/path/to/worktree", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Default case with filter path",
|
testName: "Default case with filter path",
|
||||||
filterPath: "file.txt",
|
filterPath: "file.txt",
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
expected: []string{"show", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--", "file.txt"},
|
extDiffCmd: "",
|
||||||
|
expected: []string{"-C", "/path/to/worktree", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890", "--", "file.txt"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Show diff with custom context size",
|
testName: "Show diff with custom context size",
|
||||||
filterPath: "",
|
filterPath: "",
|
||||||
contextSize: 77,
|
contextSize: 77,
|
||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
expected: []string{"show", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890"},
|
extDiffCmd: "",
|
||||||
|
expected: []string{"-C", "/path/to/worktree", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Show diff, ignoring whitespace",
|
testName: "Show diff, ignoring whitespace",
|
||||||
filterPath: "",
|
filterPath: "",
|
||||||
contextSize: 77,
|
contextSize: 77,
|
||||||
ignoreWhitespace: true,
|
ignoreWhitespace: true,
|
||||||
expected: []string{"show", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--ignore-all-space"},
|
extDiffCmd: "",
|
||||||
|
expected: []string{"-C", "/path/to/worktree", "show", "--no-ext-diff", "--submodule", "--color=always", "--unified=77", "--stat", "--decorate", "-p", "1234567890", "--ignore-all-space"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "Show diff with external diff command",
|
||||||
|
filterPath: "",
|
||||||
|
contextSize: 3,
|
||||||
|
ignoreWhitespace: false,
|
||||||
|
extDiffCmd: "difft --color=always",
|
||||||
|
expected: []string{"-C", "/path/to/worktree", "-c", "diff.external=difft --color=always", "show", "--ext-diff", "--submodule", "--color=always", "--unified=3", "--stat", "--decorate", "-p", "1234567890"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,12 +237,18 @@ func TestCommitShowCmdObj(t *testing.T) {
|
|||||||
s := s
|
s := s
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
userConfig := config.GetDefaultConfig()
|
userConfig := config.GetDefaultConfig()
|
||||||
userConfig.Git.DiffContextSize = s.contextSize
|
userConfig.Git.Paging.ExternalDiffCommand = s.extDiffCmd
|
||||||
|
appState := &config.AppState{}
|
||||||
|
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
|
||||||
|
appState.DiffContextSize = s.contextSize
|
||||||
|
|
||||||
runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expected, "", nil)
|
runner := oscommands.NewFakeRunner(t).ExpectGitArgs(s.expected, "", nil)
|
||||||
instance := buildCommitCommands(commonDeps{userConfig: userConfig, runner: runner})
|
repoPaths := RepoPaths{
|
||||||
|
worktreePath: "/path/to/worktree",
|
||||||
|
}
|
||||||
|
instance := buildCommitCommands(commonDeps{userConfig: userConfig, appState: appState, runner: runner, repoPaths: &repoPaths})
|
||||||
|
|
||||||
assert.NoError(t, instance.ShowCmdObj("1234567890", s.filterPath, s.ignoreWhitespace).Run())
|
assert.NoError(t, instance.ShowCmdObj("1234567890", s.filterPath).Run())
|
||||||
runner.CheckForMissingCalls()
|
runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -239,19 +263,17 @@ func TestGetCommitMsg(t *testing.T) {
|
|||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"empty",
|
"empty",
|
||||||
` commit deadbeef`,
|
``,
|
||||||
``,
|
``,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"no line breaks (single line)",
|
"no line breaks (single line)",
|
||||||
`commit deadbeef
|
`use generics to DRY up context code`,
|
||||||
use generics to DRY up context code`,
|
|
||||||
`use generics to DRY up context code`,
|
`use generics to DRY up context code`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"with line breaks",
|
"with line breaks",
|
||||||
`commit deadbeef
|
`Merge pull request #1750 from mark2185/fix-issue-template
|
||||||
Merge pull request #1750 from mark2185/fix-issue-template
|
|
||||||
|
|
||||||
'git-rev parse' should be 'git rev-parse'`,
|
'git-rev parse' should be 'git rev-parse'`,
|
||||||
`Merge pull request #1750 from mark2185/fix-issue-template
|
`Merge pull request #1750 from mark2185/fix-issue-template
|
||||||
@@ -264,7 +286,7 @@ Merge pull request #1750 from mark2185/fix-issue-template
|
|||||||
s := s
|
s := s
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
instance := buildCommitCommands(commonDeps{
|
instance := buildCommitCommands(commonDeps{
|
||||||
runner: oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"rev-list", "--format=%B", "--max-count=1", "deadbeef"}, s.input, nil),
|
runner: oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "--format=%B", "--max-count=1", "deadbeef"}, s.input, nil),
|
||||||
})
|
})
|
||||||
|
|
||||||
output, err := instance.GetCommitMessage("deadbeef")
|
output, err := instance.GetCommitMessage("deadbeef")
|
||||||
@@ -285,15 +307,14 @@ func TestGetCommitMessageFromHistory(t *testing.T) {
|
|||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
"Empty message",
|
"Empty message",
|
||||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "", nil).ExpectGitArgs([]string{"rev-list", "--format=%B", "--max-count=1"}, "", nil),
|
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "", nil).ExpectGitArgs([]string{"log", "--format=%B", "--max-count=1"}, "", nil),
|
||||||
func(output string, err error) {
|
func(output string, err error) {
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Default case to retrieve a commit in history",
|
"Default case to retrieve a commit in history",
|
||||||
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "sha3 \n", nil).ExpectGitArgs([]string{"rev-list", "--format=%B", "--max-count=1", "sha3"}, `commit sha3
|
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"log", "-1", "--skip=2", "--pretty=%H"}, "sha3 \n", nil).ExpectGitArgs([]string{"log", "--format=%B", "--max-count=1", "sha3"}, `use generics to DRY up context code`, nil),
|
||||||
use generics to DRY up context code`, nil),
|
|
||||||
func(output string, err error) {
|
func(output string, err error) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "use generics to DRY up context code", output)
|
assert.Equal(t, "use generics to DRY up context code", output)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
gogit "github.com/jesseduffield/go-git/v5"
|
gogit "github.com/jesseduffield/go-git/v5"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/sasha-s/go-deadlock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type GitCommon struct {
|
type GitCommon struct {
|
||||||
@@ -12,11 +11,9 @@ type GitCommon struct {
|
|||||||
version *GitVersion
|
version *GitVersion
|
||||||
cmd oscommands.ICmdObjBuilder
|
cmd oscommands.ICmdObjBuilder
|
||||||
os *oscommands.OSCommand
|
os *oscommands.OSCommand
|
||||||
dotGitDir string
|
repoPaths *RepoPaths
|
||||||
repo *gogit.Repository
|
repo *gogit.Repository
|
||||||
config *ConfigCommands
|
config *ConfigCommands
|
||||||
// mutex for doing things like push/pull/fetch
|
|
||||||
syncMutex *deadlock.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGitCommon(
|
func NewGitCommon(
|
||||||
@@ -24,19 +21,17 @@ func NewGitCommon(
|
|||||||
version *GitVersion,
|
version *GitVersion,
|
||||||
cmd oscommands.ICmdObjBuilder,
|
cmd oscommands.ICmdObjBuilder,
|
||||||
osCommand *oscommands.OSCommand,
|
osCommand *oscommands.OSCommand,
|
||||||
dotGitDir string,
|
repoPaths *RepoPaths,
|
||||||
repo *gogit.Repository,
|
repo *gogit.Repository,
|
||||||
config *ConfigCommands,
|
config *ConfigCommands,
|
||||||
syncMutex *deadlock.Mutex,
|
|
||||||
) *GitCommon {
|
) *GitCommon {
|
||||||
return &GitCommon{
|
return &GitCommon{
|
||||||
Common: cmn,
|
Common: cmn,
|
||||||
version: version,
|
version: version,
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
os: osCommand,
|
os: osCommand,
|
||||||
dotGitDir: dotGitDir,
|
repoPaths: repoPaths,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
config: config,
|
config: config,
|
||||||
syncMutex: syncMutex,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func (self *ConfigCommands) GetPager(width int) string {
|
|||||||
"columnWidth": strconv.Itoa(width/2 - 6),
|
"columnWidth": strconv.Itoa(width/2 - 6),
|
||||||
}
|
}
|
||||||
|
|
||||||
pagerTemplate := self.UserConfig.Git.Paging.Pager
|
pagerTemplate := string(self.UserConfig.Git.Paging.Pager)
|
||||||
return utils.ResolvePlaceholderString(pagerTemplate, templateValues)
|
return utils.ResolvePlaceholderString(pagerTemplate, templateValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,3 +107,7 @@ func (self *ConfigCommands) GetCoreCommentChar() byte {
|
|||||||
|
|
||||||
return '#'
|
return '#'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ConfigCommands) GetRebaseUpdateRefs() bool {
|
||||||
|
return self.gitConfig.GetBool("rebase.updateRefs")
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,18 +11,21 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/config"
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
type commonDeps struct {
|
type commonDeps struct {
|
||||||
runner *oscommands.FakeCmdObjRunner
|
runner *oscommands.FakeCmdObjRunner
|
||||||
userConfig *config.UserConfig
|
userConfig *config.UserConfig
|
||||||
|
appState *config.AppState
|
||||||
gitVersion *GitVersion
|
gitVersion *GitVersion
|
||||||
gitConfig *git_config.FakeGitConfig
|
gitConfig *git_config.FakeGitConfig
|
||||||
getenv func(string) string
|
getenv func(string) string
|
||||||
removeFile func(string) error
|
removeFile func(string) error
|
||||||
dotGitDir string
|
|
||||||
common *common.Common
|
common *common.Common
|
||||||
cmd *oscommands.CmdObjBuilder
|
cmd *oscommands.CmdObjBuilder
|
||||||
|
fs afero.Fs
|
||||||
|
repoPaths *RepoPaths
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildGitCommon(deps commonDeps) *GitCommon {
|
func buildGitCommon(deps commonDeps) *GitCommon {
|
||||||
@@ -30,7 +33,17 @@ func buildGitCommon(deps commonDeps) *GitCommon {
|
|||||||
|
|
||||||
gitCommon.Common = deps.common
|
gitCommon.Common = deps.common
|
||||||
if gitCommon.Common == nil {
|
if gitCommon.Common == nil {
|
||||||
gitCommon.Common = utils.NewDummyCommonWithUserConfig(deps.userConfig)
|
gitCommon.Common = utils.NewDummyCommonWithUserConfigAndAppState(deps.userConfig, deps.appState)
|
||||||
|
}
|
||||||
|
|
||||||
|
if deps.fs != nil {
|
||||||
|
gitCommon.Fs = deps.fs
|
||||||
|
}
|
||||||
|
|
||||||
|
if deps.repoPaths != nil {
|
||||||
|
gitCommon.repoPaths = deps.repoPaths
|
||||||
|
} else {
|
||||||
|
gitCommon.repoPaths = MockRepoPaths(".git")
|
||||||
}
|
}
|
||||||
|
|
||||||
runner := deps.runner
|
runner := deps.runner
|
||||||
@@ -81,11 +94,6 @@ func buildGitCommon(deps commonDeps) *GitCommon {
|
|||||||
TempDir: os.TempDir(),
|
TempDir: os.TempDir(),
|
||||||
})
|
})
|
||||||
|
|
||||||
gitCommon.dotGitDir = deps.dotGitDir
|
|
||||||
if gitCommon.dotGitDir == "" {
|
|
||||||
gitCommon.dotGitDir = ".git"
|
|
||||||
}
|
|
||||||
|
|
||||||
return gitCommon
|
return gitCommon
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +104,7 @@ func buildRepo() *gogit.Repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildFileLoader(gitCommon *GitCommon) *FileLoader {
|
func buildFileLoader(gitCommon *GitCommon) *FileLoader {
|
||||||
return NewFileLoader(gitCommon.Common, gitCommon.cmd, gitCommon.config)
|
return NewFileLoader(gitCommon, gitCommon.cmd, gitCommon.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSubmoduleCommands(deps commonDeps) *SubmoduleCommands {
|
func buildSubmoduleCommands(deps commonDeps) *SubmoduleCommands {
|
||||||
@@ -118,7 +126,7 @@ func buildWorkingTreeCommands(deps commonDeps) *WorkingTreeCommands {
|
|||||||
return NewWorkingTreeCommands(gitCommon, submoduleCommands, fileLoader)
|
return NewWorkingTreeCommands(gitCommon, submoduleCommands, fileLoader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPatchCommands(deps commonDeps) *PatchCommands {
|
func buildPatchCommands(deps commonDeps) *PatchCommands { //nolint:golint,unused
|
||||||
gitCommon := buildGitCommon(deps)
|
gitCommon := buildGitCommon(deps)
|
||||||
rebaseCommands := buildRebaseCommands(deps)
|
rebaseCommands := buildRebaseCommands(deps)
|
||||||
commitCommands := buildCommitCommands(deps)
|
commitCommands := buildCommitCommands(deps)
|
||||||
@@ -132,7 +140,7 @@ func buildPatchCommands(deps commonDeps) *PatchCommands {
|
|||||||
return NewPatchCommands(gitCommon, rebaseCommands, commitCommands, statusCommands, stashCommands, patchBuilder)
|
return NewPatchCommands(gitCommon, rebaseCommands, commitCommands, statusCommands, stashCommands, patchBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildStatusCommands(deps commonDeps) *StatusCommands {
|
func buildStatusCommands(deps commonDeps) *StatusCommands { //nolint:golint,unused
|
||||||
gitCommon := buildGitCommon(deps)
|
gitCommon := buildGitCommon(deps)
|
||||||
|
|
||||||
return NewStatusCommands(gitCommon)
|
return NewStatusCommands(gitCommon)
|
||||||
|
|||||||
@@ -14,6 +14,80 @@ func NewDiffCommands(gitCommon *GitCommon) *DiffCommands {
|
|||||||
|
|
||||||
func (self *DiffCommands) DiffCmdObj(diffArgs []string) oscommands.ICmdObj {
|
func (self *DiffCommands) DiffCmdObj(diffArgs []string) oscommands.ICmdObj {
|
||||||
return self.cmd.New(
|
return self.cmd.New(
|
||||||
NewGitCmd("diff").Arg("--submodule", "--no-ext-diff", "--color").Arg(diffArgs...).ToArgv(),
|
NewGitCmd("diff").
|
||||||
|
Arg("--submodule", "--no-ext-diff", "--color").
|
||||||
|
Arg(diffArgs...).
|
||||||
|
Dir(self.repoPaths.worktreePath).
|
||||||
|
ToArgv(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DiffCommands) internalDiffCmdObj(diffArgs ...string) *GitCommandBuilder {
|
||||||
|
return NewGitCmd("diff").
|
||||||
|
Arg("--no-ext-diff", "--no-color").
|
||||||
|
Arg(diffArgs...).
|
||||||
|
Dir(self.repoPaths.worktreePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DiffCommands) GetPathDiff(path string, staged bool) (string, error) {
|
||||||
|
return self.cmd.New(
|
||||||
|
self.internalDiffCmdObj().
|
||||||
|
ArgIf(staged, "--staged").
|
||||||
|
Arg(path).
|
||||||
|
ToArgv(),
|
||||||
|
).RunWithOutput()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DiffCommands) GetAllDiff(staged bool) (string, error) {
|
||||||
|
return self.cmd.New(
|
||||||
|
self.internalDiffCmdObj().
|
||||||
|
ArgIf(staged, "--staged").
|
||||||
|
ToArgv(),
|
||||||
|
).RunWithOutput()
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiffToolCmdOptions struct {
|
||||||
|
// The path to show a diff for. Pass "." for the entire repo.
|
||||||
|
Filepath string
|
||||||
|
|
||||||
|
// The commit against which to show the diff. Leave empty to show a diff of
|
||||||
|
// the working copy.
|
||||||
|
FromCommit string
|
||||||
|
|
||||||
|
// The commit to diff against FromCommit. Leave empty to diff the working
|
||||||
|
// copy against FromCommit. Leave both FromCommit and ToCommit empty to show
|
||||||
|
// the diff of the unstaged working copy changes against the index if Staged
|
||||||
|
// is false, or the staged changes against HEAD if Staged is true.
|
||||||
|
ToCommit string
|
||||||
|
|
||||||
|
// Whether to reverse the left and right sides of the diff.
|
||||||
|
Reverse bool
|
||||||
|
|
||||||
|
// Whether the given Filepath is a directory. We'll pass --dir-diff to
|
||||||
|
// git-difftool in that case.
|
||||||
|
IsDirectory bool
|
||||||
|
|
||||||
|
// Whether to show the staged or the unstaged changes. Must be false if both
|
||||||
|
// FromCommit and ToCommit are non-empty.
|
||||||
|
Staged bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DiffCommands) OpenDiffToolCmdObj(opts DiffToolCmdOptions) oscommands.ICmdObj {
|
||||||
|
return self.cmd.New(NewGitCmd("difftool").
|
||||||
|
Arg("--no-prompt").
|
||||||
|
ArgIf(opts.IsDirectory, "--dir-diff").
|
||||||
|
ArgIf(opts.Staged, "--cached").
|
||||||
|
ArgIf(opts.FromCommit != "", opts.FromCommit).
|
||||||
|
ArgIf(opts.ToCommit != "", opts.ToCommit).
|
||||||
|
ArgIf(opts.Reverse, "-R").
|
||||||
|
Arg("--", opts.Filepath).
|
||||||
|
ToArgv())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *DiffCommands) DiffIndexCmdObj(diffArgs ...string) oscommands.ICmdObj {
|
||||||
|
return self.cmd.New(
|
||||||
|
NewGitCmd("diff-index").
|
||||||
|
Arg("--submodule", "--no-ext-diff", "--no-color", "--patch").
|
||||||
|
Arg(diffArgs...).ToArgv(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,14 +83,14 @@ func (self *FileCommands) GetEditCmdStr(filename string) (string, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template, editInTerminal := config.GetEditTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
template, suspend := config.GetEditTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||||
|
|
||||||
templateValues := map[string]string{
|
templateValues := map[string]string{
|
||||||
"filename": self.cmd.Quote(filename),
|
"filename": self.cmd.Quote(filename),
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdStr := utils.ResolvePlaceholderString(template, templateValues)
|
cmdStr := utils.ResolvePlaceholderString(template, templateValues)
|
||||||
return cmdStr, editInTerminal
|
return cmdStr, suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (string, bool) {
|
func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (string, bool) {
|
||||||
@@ -101,7 +101,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template, editInTerminal := config.GetEditAtLineTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
template, suspend := config.GetEditAtLineTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||||
|
|
||||||
templateValues := map[string]string{
|
templateValues := map[string]string{
|
||||||
"filename": self.cmd.Quote(filename),
|
"filename": self.cmd.Quote(filename),
|
||||||
@@ -109,7 +109,7 @@ func (self *FileCommands) GetEditAtLineCmdStr(filename string, lineNumber int) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmdStr := utils.ResolvePlaceholderString(template, templateValues)
|
cmdStr := utils.ResolvePlaceholderString(template, templateValues)
|
||||||
return cmdStr, editInTerminal
|
return cmdStr, suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber int) string {
|
func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber int) string {
|
||||||
@@ -131,6 +131,17 @@ func (self *FileCommands) GetEditAtLineAndWaitCmdStr(filename string, lineNumber
|
|||||||
return cmdStr
|
return cmdStr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *FileCommands) GetOpenDirInEditorCmdStr(path string) (string, bool) {
|
||||||
|
template, suspend := config.GetOpenDirInEditorTemplate(&self.UserConfig.OS, self.guessDefaultEditor)
|
||||||
|
|
||||||
|
templateValues := map[string]string{
|
||||||
|
"dir": self.cmd.Quote(path),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdStr := utils.ResolvePlaceholderString(template, templateValues)
|
||||||
|
return cmdStr, suspend
|
||||||
|
}
|
||||||
|
|
||||||
func (self *FileCommands) guessDefaultEditor() string {
|
func (self *FileCommands) guessDefaultEditor() string {
|
||||||
// Try to query a few places where editors get configured
|
// Try to query a few places where editors get configured
|
||||||
editor := self.config.GetCoreEditor()
|
editor := self.config.GetCoreEditor()
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package git_commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileLoaderConfig interface {
|
type FileLoaderConfig interface {
|
||||||
@@ -14,15 +14,15 @@ type FileLoaderConfig interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FileLoader struct {
|
type FileLoader struct {
|
||||||
*common.Common
|
*GitCommon
|
||||||
cmd oscommands.ICmdObjBuilder
|
cmd oscommands.ICmdObjBuilder
|
||||||
config FileLoaderConfig
|
config FileLoaderConfig
|
||||||
getFileType func(string) string
|
getFileType func(string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFileLoader(cmn *common.Common, cmd oscommands.ICmdObjBuilder, config FileLoaderConfig) *FileLoader {
|
func NewFileLoader(gitCommon *GitCommon, cmd oscommands.ICmdObjBuilder, config FileLoaderConfig) *FileLoader {
|
||||||
return &FileLoader{
|
return &FileLoader{
|
||||||
Common: cmn,
|
GitCommon: gitCommon,
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
getFileType: oscommands.FileType,
|
getFileType: oscommands.FileType,
|
||||||
config: config,
|
config: config,
|
||||||
@@ -58,13 +58,32 @@ func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File
|
|||||||
Name: status.Name,
|
Name: status.Name,
|
||||||
PreviousName: status.PreviousName,
|
PreviousName: status.PreviousName,
|
||||||
DisplayString: status.StatusString,
|
DisplayString: status.StatusString,
|
||||||
Type: self.getFileType(status.Name),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
models.SetStatusFields(file, status.Change)
|
models.SetStatusFields(file, status.Change)
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go through the files to see if any of these files are actually worktrees
|
||||||
|
// so that we can render them correctly
|
||||||
|
worktreePaths := linkedWortkreePaths(self.Fs, self.repoPaths.RepoGitDirPath())
|
||||||
|
for _, file := range files {
|
||||||
|
for _, worktreePath := range worktreePaths {
|
||||||
|
absFilePath, err := filepath.Abs(file.Name)
|
||||||
|
if err != nil {
|
||||||
|
self.Log.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if absFilePath == worktreePath {
|
||||||
|
file.IsWorktree = true
|
||||||
|
// `git status` renders this worktree as a folder with a trailing slash but we'll represent it as a singular worktree
|
||||||
|
// If we include the slash, it will be rendered as a folder with a null file inside.
|
||||||
|
file.Name = strings.TrimSuffix(file.Name, "/")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "MM file1.txt",
|
DisplayString: "MM file1.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "MM",
|
ShortStatus: "MM",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -54,7 +52,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "A file3.txt",
|
DisplayString: "A file3.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "A ",
|
ShortStatus: "A ",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -67,7 +64,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "AM file2.txt",
|
DisplayString: "AM file2.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "AM",
|
ShortStatus: "AM",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -80,7 +76,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "?? file4.txt",
|
DisplayString: "?? file4.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "??",
|
ShortStatus: "??",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -93,7 +88,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: true,
|
HasMergeConflicts: true,
|
||||||
HasInlineMergeConflicts: true,
|
HasInlineMergeConflicts: true,
|
||||||
DisplayString: "UU file5.txt",
|
DisplayString: "UU file5.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "UU",
|
ShortStatus: "UU",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -113,7 +107,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "MM a\nb.txt",
|
DisplayString: "MM a\nb.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "MM",
|
ShortStatus: "MM",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -137,7 +130,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "R before1.txt -> after1.txt",
|
DisplayString: "R before1.txt -> after1.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "R ",
|
ShortStatus: "R ",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -151,7 +143,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "RM before2.txt -> after2.txt",
|
DisplayString: "RM before2.txt -> after2.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "RM",
|
ShortStatus: "RM",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -174,7 +165,6 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
HasMergeConflicts: false,
|
HasMergeConflicts: false,
|
||||||
HasInlineMergeConflicts: false,
|
HasInlineMergeConflicts: false,
|
||||||
DisplayString: "?? a -> b.txt",
|
DisplayString: "?? a -> b.txt",
|
||||||
Type: "file",
|
|
||||||
ShortStatus: "??",
|
ShortStatus: "??",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -187,7 +177,7 @@ func TestFileGetStatusFiles(t *testing.T) {
|
|||||||
cmd := oscommands.NewDummyCmdObjBuilder(s.runner)
|
cmd := oscommands.NewDummyCmdObjBuilder(s.runner)
|
||||||
|
|
||||||
loader := &FileLoader{
|
loader := &FileLoader{
|
||||||
Common: utils.NewDummyCommon(),
|
GitCommon: buildGitCommon(commonDeps{}),
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
config: &FakeFileLoaderConfig{showUntrackedFiles: "yes"},
|
config: &FakeFileLoaderConfig{showUntrackedFiles: "yes"},
|
||||||
getFileType: func(string) string { return "file" },
|
getFileType: func(string) string { return "file" },
|
||||||
|
|||||||
@@ -179,34 +179,34 @@ func TestEditFileCmdStrLegacy(t *testing.T) {
|
|||||||
|
|
||||||
func TestEditFileCmd(t *testing.T) {
|
func TestEditFileCmd(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
filename string
|
filename string
|
||||||
osConfig config.OSConfig
|
osConfig config.OSConfig
|
||||||
expectedCmdStr string
|
expectedCmdStr string
|
||||||
expectedEditInTerminal bool
|
suspend bool
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
filename: "test",
|
filename: "test",
|
||||||
osConfig: config.OSConfig{},
|
osConfig: config.OSConfig{},
|
||||||
expectedCmdStr: `vim -- "test"`,
|
expectedCmdStr: `vim -- "test"`,
|
||||||
expectedEditInTerminal: true,
|
suspend: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filename: "test",
|
filename: "test",
|
||||||
osConfig: config.OSConfig{
|
osConfig: config.OSConfig{
|
||||||
Edit: "nano {{filename}}",
|
Edit: "nano {{filename}}",
|
||||||
},
|
},
|
||||||
expectedCmdStr: `nano "test"`,
|
expectedCmdStr: `nano "test"`,
|
||||||
expectedEditInTerminal: true,
|
suspend: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filename: "file/with space",
|
filename: "file/with space",
|
||||||
osConfig: config.OSConfig{
|
osConfig: config.OSConfig{
|
||||||
EditPreset: "sublime",
|
EditPreset: "sublime",
|
||||||
},
|
},
|
||||||
expectedCmdStr: `subl -- "file/with space"`,
|
expectedCmdStr: `subl -- "file/with space"`,
|
||||||
expectedEditInTerminal: false,
|
suspend: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,28 +218,28 @@ func TestEditFileCmd(t *testing.T) {
|
|||||||
userConfig: userConfig,
|
userConfig: userConfig,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmdStr, editInTerminal := instance.GetEditCmdStr(s.filename)
|
cmdStr, suspend := instance.GetEditCmdStr(s.filename)
|
||||||
assert.Equal(t, s.expectedCmdStr, cmdStr)
|
assert.Equal(t, s.expectedCmdStr, cmdStr)
|
||||||
assert.Equal(t, s.expectedEditInTerminal, editInTerminal)
|
assert.Equal(t, s.suspend, suspend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEditFileAtLineCmd(t *testing.T) {
|
func TestEditFileAtLineCmd(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
filename string
|
filename string
|
||||||
lineNumber int
|
lineNumber int
|
||||||
osConfig config.OSConfig
|
osConfig config.OSConfig
|
||||||
expectedCmdStr string
|
expectedCmdStr string
|
||||||
expectedEditInTerminal bool
|
suspend bool
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarios := []scenario{
|
scenarios := []scenario{
|
||||||
{
|
{
|
||||||
filename: "test",
|
filename: "test",
|
||||||
lineNumber: 42,
|
lineNumber: 42,
|
||||||
osConfig: config.OSConfig{},
|
osConfig: config.OSConfig{},
|
||||||
expectedCmdStr: `vim +42 -- "test"`,
|
expectedCmdStr: `vim +42 -- "test"`,
|
||||||
expectedEditInTerminal: true,
|
suspend: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filename: "test",
|
filename: "test",
|
||||||
@@ -247,8 +247,8 @@ func TestEditFileAtLineCmd(t *testing.T) {
|
|||||||
osConfig: config.OSConfig{
|
osConfig: config.OSConfig{
|
||||||
EditAtLine: "nano +{{line}} {{filename}}",
|
EditAtLine: "nano +{{line}} {{filename}}",
|
||||||
},
|
},
|
||||||
expectedCmdStr: `nano +35 "test"`,
|
expectedCmdStr: `nano +35 "test"`,
|
||||||
expectedEditInTerminal: true,
|
suspend: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
filename: "file/with space",
|
filename: "file/with space",
|
||||||
@@ -256,8 +256,8 @@ func TestEditFileAtLineCmd(t *testing.T) {
|
|||||||
osConfig: config.OSConfig{
|
osConfig: config.OSConfig{
|
||||||
EditPreset: "sublime",
|
EditPreset: "sublime",
|
||||||
},
|
},
|
||||||
expectedCmdStr: `subl -- "file/with space":12`,
|
expectedCmdStr: `subl -- "file/with space":12`,
|
||||||
expectedEditInTerminal: false,
|
suspend: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,9 +269,9 @@ func TestEditFileAtLineCmd(t *testing.T) {
|
|||||||
userConfig: userConfig,
|
userConfig: userConfig,
|
||||||
})
|
})
|
||||||
|
|
||||||
cmdStr, editInTerminal := instance.GetEditAtLineCmdStr(s.filename, s.lineNumber)
|
cmdStr, suspend := instance.GetEditAtLineCmdStr(s.filename, s.lineNumber)
|
||||||
assert.Equal(t, s.expectedCmdStr, cmdStr)
|
assert.Equal(t, s.expectedCmdStr, cmdStr)
|
||||||
assert.Equal(t, s.expectedEditInTerminal, editInTerminal)
|
assert.Equal(t, s.suspend, suspend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package git_commands
|
package git_commands
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// convenience struct for building git commands. Especially useful when
|
// convenience struct for building git commands. Especially useful when
|
||||||
// including conditional args
|
// including conditional args
|
||||||
@@ -42,9 +44,42 @@ func (self *GitCommandBuilder) Config(value string) *GitCommandBuilder {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *GitCommandBuilder) RepoPath(value string) *GitCommandBuilder {
|
func (self *GitCommandBuilder) ConfigIf(condition bool, ifTrue string) *GitCommandBuilder {
|
||||||
|
if condition {
|
||||||
|
self.Config(ifTrue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
// the -C arg will make git do a `cd` to the directory before doing anything else
|
||||||
|
func (self *GitCommandBuilder) Dir(path string) *GitCommandBuilder {
|
||||||
// repo path comes before the command
|
// repo path comes before the command
|
||||||
self.args = append([]string{"-C", value}, self.args...)
|
self.args = append([]string{"-C", path}, self.args...)
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, you may prefer to use the Dir method instead of this one
|
||||||
|
func (self *GitCommandBuilder) Worktree(path string) *GitCommandBuilder {
|
||||||
|
// worktree arg comes before the command
|
||||||
|
self.args = append([]string{"--work-tree", path}, self.args...)
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, you may prefer to use the Dir method instead of this one
|
||||||
|
func (self *GitCommandBuilder) GitDir(path string) *GitCommandBuilder {
|
||||||
|
// git dir arg comes before the command
|
||||||
|
self.args = append([]string{"--git-dir", path}, self.args...)
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *GitCommandBuilder) GitDirIf(condition bool, path string) *GitCommandBuilder {
|
||||||
|
if condition {
|
||||||
|
return self.GitDir(path)
|
||||||
|
}
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func TestGitCommandBuilder(t *testing.T) {
|
|||||||
expected: []string{"git", "-c", "user.email=bar", "-c", "user.name=foo", "push"},
|
expected: []string{"git", "-c", "user.email=bar", "-c", "user.name=foo", "push"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: NewGitCmd("push").RepoPath("a/b/c").ToArgv(),
|
input: NewGitCmd("push").Dir("a/b/c").ToArgv(),
|
||||||
expected: []string{"git", "-C", "a/b/c", "push"},
|
expected: []string{"git", "-C", "a/b/c", "push"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package git_commands
|
package git_commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
"github.com/jesseduffield/lazygit/pkg/commands/patch"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type PatchCommands struct {
|
type PatchCommands struct {
|
||||||
@@ -81,7 +79,7 @@ func (self *PatchCommands) applyPatchFile(filepath string, opts ApplyPatchOpts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchCommands) SaveTemporaryPatch(patch string) (string, error) {
|
func (self *PatchCommands) SaveTemporaryPatch(patch string) (string, error) {
|
||||||
filepath := filepath.Join(self.os.GetTempDir(), utils.GetCurrentRepoName(), time.Now().Format("Jan _2 15.04.05.000000000")+".patch")
|
filepath := filepath.Join(self.os.GetTempDir(), self.repoPaths.RepoName(), time.Now().Format("Jan _2 15.04.05.000000000")+".patch")
|
||||||
self.Log.Infof("saving temporary patch to %s", filepath)
|
self.Log.Infof("saving temporary patch to %s", filepath)
|
||||||
if err := self.os.CreateFileWithContent(filepath, patch); err != nil {
|
if err := self.os.CreateFileWithContent(filepath, patch); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -274,7 +272,12 @@ func (self *PatchCommands) MovePatchIntoIndex(commits []*models.Commit, commitId
|
|||||||
return self.rebase.ContinueRebase()
|
return self.rebase.ContinueRebase()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchCommands) PullPatchIntoNewCommit(commits []*models.Commit, commitIdx int) error {
|
func (self *PatchCommands) PullPatchIntoNewCommit(
|
||||||
|
commits []*models.Commit,
|
||||||
|
commitIdx int,
|
||||||
|
commitSummary string,
|
||||||
|
commitDescription string,
|
||||||
|
) error {
|
||||||
if err := self.rebase.BeginInteractiveRebaseForCommit(commits, commitIdx, false); err != nil {
|
if err := self.rebase.BeginInteractiveRebaseForCommit(commits, commitIdx, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -300,9 +303,7 @@ func (self *PatchCommands) PullPatchIntoNewCommit(commits []*models.Commit, comm
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
head_message, _ := self.commit.GetHeadCommitMessage()
|
if err := self.commit.CommitCmdObj(commitSummary, commitDescription).Run(); err != nil {
|
||||||
new_message := fmt.Sprintf("Split from \"%s\"", head_message)
|
|
||||||
if err := self.commit.CommitCmdObj(new_message).Run(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
package git_commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPatchApplyPatch(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
opts ApplyPatchOpts
|
|
||||||
runner *oscommands.FakeCmdObjRunner
|
|
||||||
test func(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// expectedArgs excludes the last argument which is an indeterminate filename
|
|
||||||
expectFn := func(expectedArgs []string, errToReturn error) func(cmdObj oscommands.ICmdObj) (string, error) {
|
|
||||||
return func(cmdObj oscommands.ICmdObj) (string, error) {
|
|
||||||
args := cmdObj.Args()
|
|
||||||
|
|
||||||
assert.Equal(t, len(args), len(expectedArgs)+1, fmt.Sprintf("unexpected command: %s", cmdObj.ToString()))
|
|
||||||
|
|
||||||
filename := args[len(args)-1]
|
|
||||||
|
|
||||||
content, err := os.ReadFile(filename)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, "test", string(content))
|
|
||||||
|
|
||||||
return "", errToReturn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
testName: "valid case",
|
|
||||||
opts: ApplyPatchOpts{Cached: true},
|
|
||||||
runner: oscommands.NewFakeRunner(t).
|
|
||||||
ExpectFunc(expectFn([]string{"git", "apply", "--cached"}, nil)),
|
|
||||||
test: func(err error) {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
testName: "command returns error",
|
|
||||||
opts: ApplyPatchOpts{Cached: true},
|
|
||||||
runner: oscommands.NewFakeRunner(t).
|
|
||||||
ExpectFunc(expectFn([]string{"git", "apply", "--cached"}, errors.New("error"))),
|
|
||||||
test: func(err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
s := s
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
instance := buildPatchCommands(commonDeps{runner: s.runner})
|
|
||||||
s.test(instance.ApplyPatch("test", s.opts))
|
|
||||||
s.runner.CheckForMissingCalls()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/fsmiamoto/git-todo-parser/todo"
|
"github.com/fsmiamoto/git-todo-parser/todo"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/app/daemon"
|
"github.com/jesseduffield/lazygit/pkg/app/daemon"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
@@ -35,10 +34,10 @@ func NewRebaseCommands(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, message string) error {
|
func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, summary string, description string) error {
|
||||||
if models.IsHeadCommit(commits, index) {
|
if models.IsHeadCommit(commits, index) {
|
||||||
// we've selected the top commit so no rebase is required
|
// we've selected the top commit so no rebase is required
|
||||||
return self.commit.RewordLastCommit(message)
|
return self.commit.RewordLastCommit(summary, description)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := self.BeginInteractiveRebaseForCommit(commits, index, false)
|
err := self.BeginInteractiveRebaseForCommit(commits, index, false)
|
||||||
@@ -47,7 +46,7 @@ func (self *RebaseCommands) RewordCommit(commits []*models.Commit, index int, me
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now the selected commit should be our head so we'll amend it with the new message
|
// now the selected commit should be our head so we'll amend it with the new message
|
||||||
err = self.commit.RewordLastCommit(message)
|
err = self.commit.RewordLastCommit(summary, description)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -80,6 +79,12 @@ func (self *RebaseCommands) SetCommitAuthor(commits []*models.Commit, index int,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RebaseCommands) AddCommitCoAuthor(commits []*models.Commit, index int, value string) error {
|
||||||
|
return self.GenericAmend(commits, index, func() error {
|
||||||
|
return self.commit.AddCoAuthor(commits[index].Sha, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) GenericAmend(commits []*models.Commit, index int, f func() error) error {
|
func (self *RebaseCommands) GenericAmend(commits []*models.Commit, index int, f func() error) error {
|
||||||
if models.IsHeadCommit(commits, index) {
|
if models.IsHeadCommit(commits, index) {
|
||||||
// we've selected the top commit so no rebase is required
|
// we've selected the top commit so no rebase is required
|
||||||
@@ -100,46 +105,49 @@ func (self *RebaseCommands) GenericAmend(commits []*models.Commit, index int, f
|
|||||||
return self.ContinueRebase()
|
return self.ContinueRebase()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) MoveCommitDown(commits []*models.Commit, index int) error {
|
func (self *RebaseCommands) MoveCommitsDown(commits []*models.Commit, startIdx int, endIdx int) error {
|
||||||
baseShaOrRoot := getBaseShaOrRoot(commits, index+2)
|
baseShaOrRoot := getBaseShaOrRoot(commits, endIdx+2)
|
||||||
|
|
||||||
sha := commits[index].Sha
|
shas := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
|
||||||
|
return commit.Sha
|
||||||
self.os.LogCommand(fmt.Sprintf("Moving TODO down: %s", utils.ShortSha(sha)), false)
|
})
|
||||||
|
|
||||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
baseShaOrRoot: baseShaOrRoot,
|
baseShaOrRoot: baseShaOrRoot,
|
||||||
instruction: daemon.NewMoveTodoDownInstruction(sha),
|
instruction: daemon.NewMoveTodosDownInstruction(shas),
|
||||||
overrideEditor: true,
|
overrideEditor: true,
|
||||||
}).Run()
|
}).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) MoveCommitUp(commits []*models.Commit, index int) error {
|
func (self *RebaseCommands) MoveCommitsUp(commits []*models.Commit, startIdx int, endIdx int) error {
|
||||||
baseShaOrRoot := getBaseShaOrRoot(commits, index+1)
|
baseShaOrRoot := getBaseShaOrRoot(commits, endIdx+1)
|
||||||
|
|
||||||
sha := commits[index].Sha
|
shas := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) string {
|
||||||
|
return commit.Sha
|
||||||
self.os.LogCommand(fmt.Sprintf("Moving TODO up: %s", utils.ShortSha(sha)), false)
|
})
|
||||||
|
|
||||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
baseShaOrRoot: baseShaOrRoot,
|
baseShaOrRoot: baseShaOrRoot,
|
||||||
instruction: daemon.NewMoveTodoUpInstruction(sha),
|
instruction: daemon.NewMoveTodosUpInstruction(shas),
|
||||||
overrideEditor: true,
|
overrideEditor: true,
|
||||||
}).Run()
|
}).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index int, action todo.TodoCommand) error {
|
func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, startIdx int, endIdx int, action todo.TodoCommand) error {
|
||||||
baseIndex := index + 1
|
baseIndex := endIdx + 1
|
||||||
if action == todo.Squash || action == todo.Fixup {
|
if action == todo.Squash || action == todo.Fixup {
|
||||||
baseIndex++
|
baseIndex++
|
||||||
}
|
}
|
||||||
|
|
||||||
baseShaOrRoot := getBaseShaOrRoot(commits, baseIndex)
|
baseShaOrRoot := getBaseShaOrRoot(commits, baseIndex)
|
||||||
|
|
||||||
changes := []daemon.ChangeTodoAction{{
|
changes := lo.Map(commits[startIdx:endIdx+1], func(commit *models.Commit, _ int) daemon.ChangeTodoAction {
|
||||||
Sha: commits[index].Sha,
|
return daemon.ChangeTodoAction{
|
||||||
NewAction: action,
|
Sha: commit.Sha,
|
||||||
}}
|
NewAction: action,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
self.os.LogCommand(logTodoChanges(changes), false)
|
self.os.LogCommand(logTodoChanges(changes), false)
|
||||||
|
|
||||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
@@ -150,22 +158,45 @@ func (self *RebaseCommands) InteractiveRebase(commits []*models.Commit, index in
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) EditRebase(branchRef string) error {
|
func (self *RebaseCommands) EditRebase(branchRef string) error {
|
||||||
self.os.LogCommand(fmt.Sprintf("Beginning interactive rebase at '%s'", branchRef), false)
|
msg := utils.ResolvePlaceholderString(
|
||||||
|
self.Tr.Log.EditRebase,
|
||||||
|
map[string]string{
|
||||||
|
"ref": branchRef,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.os.LogCommand(msg, false)
|
||||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
baseShaOrRoot: branchRef,
|
baseShaOrRoot: branchRef,
|
||||||
instruction: daemon.NewInsertBreakInstruction(),
|
instruction: daemon.NewInsertBreakInstruction(),
|
||||||
}).Run()
|
}).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RebaseCommands) EditRebaseFromBaseCommit(targetBranchName string, baseCommit string) error {
|
||||||
|
msg := utils.ResolvePlaceholderString(
|
||||||
|
self.Tr.Log.EditRebaseFromBaseCommit,
|
||||||
|
map[string]string{
|
||||||
|
"baseCommit": baseCommit,
|
||||||
|
"targetBranchName": targetBranchName,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.os.LogCommand(msg, false)
|
||||||
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
|
baseShaOrRoot: baseCommit,
|
||||||
|
onto: targetBranchName,
|
||||||
|
instruction: daemon.NewInsertBreakInstruction(),
|
||||||
|
}).Run()
|
||||||
|
}
|
||||||
|
|
||||||
func logTodoChanges(changes []daemon.ChangeTodoAction) string {
|
func logTodoChanges(changes []daemon.ChangeTodoAction) string {
|
||||||
changeTodoStr := strings.Join(slices.Map(changes, func(c daemon.ChangeTodoAction) string {
|
changeTodoStr := strings.Join(lo.Map(changes, func(c daemon.ChangeTodoAction, _ int) string {
|
||||||
return fmt.Sprintf("%s:%s", c.Sha, c.NewAction)
|
return fmt.Sprintf("%s:%s", c.Sha, c.NewAction)
|
||||||
}), "\n")
|
}), "\n")
|
||||||
return fmt.Sprintf("Changing TODO actions: %s", changeTodoStr)
|
return fmt.Sprintf("Changing TODO actions:\n%s", changeTodoStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PrepareInteractiveRebaseCommandOpts struct {
|
type PrepareInteractiveRebaseCommandOpts struct {
|
||||||
baseShaOrRoot string
|
baseShaOrRoot string
|
||||||
|
onto string
|
||||||
instruction daemon.Instruction
|
instruction daemon.Instruction
|
||||||
overrideEditor bool
|
overrideEditor bool
|
||||||
keepCommitsThatBecomeEmpty bool
|
keepCommitsThatBecomeEmpty bool
|
||||||
@@ -181,9 +212,10 @@ func (self *RebaseCommands) PrepareInteractiveRebaseCommand(opts PrepareInteract
|
|||||||
Arg("--interactive").
|
Arg("--interactive").
|
||||||
Arg("--autostash").
|
Arg("--autostash").
|
||||||
Arg("--keep-empty").
|
Arg("--keep-empty").
|
||||||
ArgIf(opts.keepCommitsThatBecomeEmpty && !self.version.IsOlderThan(2, 26, 0), "--empty=keep").
|
ArgIf(opts.keepCommitsThatBecomeEmpty && self.version.IsAtLeast(2, 26, 0), "--empty=keep").
|
||||||
Arg("--no-autosquash").
|
Arg("--no-autosquash").
|
||||||
ArgIf(!self.version.IsOlderThan(2, 22, 0), "--rebase-merges").
|
ArgIf(self.version.IsAtLeast(2, 22, 0), "--rebase-merges").
|
||||||
|
ArgIf(opts.onto != "", "--onto", opts.onto).
|
||||||
Arg(opts.baseShaOrRoot).
|
Arg(opts.baseShaOrRoot).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
@@ -240,22 +272,45 @@ func (self *RebaseCommands) AmendTo(commits []*models.Commit, commitIndex int) e
|
|||||||
}).Run()
|
}).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EditRebaseTodo sets the action for a given rebase commit in the git-rebase-todo file
|
// Sets the action for the given commits in the git-rebase-todo file
|
||||||
func (self *RebaseCommands) EditRebaseTodo(commit *models.Commit, action todo.TodoCommand) error {
|
func (self *RebaseCommands) EditRebaseTodo(commits []*models.Commit, action todo.TodoCommand) error {
|
||||||
|
commitsWithAction := lo.Map(commits, func(commit *models.Commit, _ int) utils.TodoChange {
|
||||||
|
return utils.TodoChange{
|
||||||
|
Sha: commit.Sha,
|
||||||
|
OldAction: commit.Action,
|
||||||
|
NewAction: action,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return utils.EditRebaseTodo(
|
return utils.EditRebaseTodo(
|
||||||
filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo"), commit.Sha, commit.Action, action, self.config.GetCoreCommentChar())
|
filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo"),
|
||||||
|
commitsWithAction,
|
||||||
|
self.config.GetCoreCommentChar(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveTodoDown moves a rebase todo item down by one position
|
func (self *RebaseCommands) MoveTodosDown(commits []*models.Commit) error {
|
||||||
func (self *RebaseCommands) MoveTodoDown(commit *models.Commit) error {
|
fileName := filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo")
|
||||||
fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo")
|
todosToMove := lo.Map(commits, func(commit *models.Commit, _ int) utils.Todo {
|
||||||
return utils.MoveTodoDown(fileName, commit.Sha, commit.Action, self.config.GetCoreCommentChar())
|
return utils.Todo{
|
||||||
|
Sha: commit.Sha,
|
||||||
|
Action: commit.Action,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return utils.MoveTodosDown(fileName, todosToMove, self.config.GetCoreCommentChar())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveTodoDown moves a rebase todo item down by one position
|
func (self *RebaseCommands) MoveTodosUp(commits []*models.Commit) error {
|
||||||
func (self *RebaseCommands) MoveTodoUp(commit *models.Commit) error {
|
fileName := filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge/git-rebase-todo")
|
||||||
fileName := filepath.Join(self.dotGitDir, "rebase-merge/git-rebase-todo")
|
todosToMove := lo.Map(commits, func(commit *models.Commit, _ int) utils.Todo {
|
||||||
return utils.MoveTodoUp(fileName, commit.Sha, commit.Action, self.config.GetCoreCommentChar())
|
return utils.Todo{
|
||||||
|
Sha: commit.Sha,
|
||||||
|
Action: commit.Action,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return utils.MoveTodosUp(fileName, todosToMove, self.config.GetCoreCommentChar())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SquashAllAboveFixupCommits squashes all fixup! commits above the given one
|
// SquashAllAboveFixupCommits squashes all fixup! commits above the given one
|
||||||
@@ -307,6 +362,13 @@ func (self *RebaseCommands) RebaseBranch(branchName string) error {
|
|||||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{baseShaOrRoot: branchName}).Run()
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{baseShaOrRoot: branchName}).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RebaseCommands) RebaseBranchFromBaseCommit(targetBranchName string, baseCommit string) error {
|
||||||
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
|
baseShaOrRoot: baseCommit,
|
||||||
|
onto: targetBranchName,
|
||||||
|
}).Run()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *RebaseCommands) GenericMergeOrRebaseActionCmdObj(commandType string, command string) oscommands.ICmdObj {
|
func (self *RebaseCommands) GenericMergeOrRebaseActionCmdObj(commandType string, command string) oscommands.ICmdObj {
|
||||||
cmdArgs := NewGitCmd(commandType).Arg("--" + command).ToArgv()
|
cmdArgs := NewGitCmd(commandType).Arg("--" + command).ToArgv()
|
||||||
|
|
||||||
@@ -395,7 +457,13 @@ func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error {
|
|||||||
commitLines := lo.Map(commits, func(commit *models.Commit, _ int) string {
|
commitLines := lo.Map(commits, func(commit *models.Commit, _ int) string {
|
||||||
return fmt.Sprintf("%s %s", utils.ShortSha(commit.Sha), commit.Name)
|
return fmt.Sprintf("%s %s", utils.ShortSha(commit.Sha), commit.Name)
|
||||||
})
|
})
|
||||||
self.os.LogCommand(fmt.Sprintf("Cherry-picking commits:\n%s", strings.Join(commitLines, "\n")), false)
|
msg := utils.ResolvePlaceholderString(
|
||||||
|
self.Tr.Log.CherryPickCommits,
|
||||||
|
map[string]string{
|
||||||
|
"commitLines": strings.Join(commitLines, "\n"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.os.LogCommand(msg, false)
|
||||||
|
|
||||||
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
return self.PrepareInteractiveRebaseCommand(PrepareInteractiveRebaseCommandOpts{
|
||||||
baseShaOrRoot: "HEAD",
|
baseShaOrRoot: "HEAD",
|
||||||
@@ -403,6 +471,20 @@ func (self *RebaseCommands) CherryPickCommits(commits []*models.Commit) error {
|
|||||||
}).Run()
|
}).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CherryPickCommitsDuringRebase simply prepends the given commits to the existing git-rebase-todo file
|
||||||
|
func (self *RebaseCommands) CherryPickCommitsDuringRebase(commits []*models.Commit) error {
|
||||||
|
todoLines := lo.Map(commits, func(commit *models.Commit, _ int) daemon.TodoLine {
|
||||||
|
return daemon.TodoLine{
|
||||||
|
Action: "pick",
|
||||||
|
Commit: commit,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
todo := daemon.TodoLinesToString(todoLines)
|
||||||
|
filePath := filepath.Join(self.repoPaths.worktreeGitDirPath, "rebase-merge/git-rebase-todo")
|
||||||
|
return utils.PrependStrToTodoFile(filePath, []byte(todo))
|
||||||
|
}
|
||||||
|
|
||||||
// we can't start an interactive rebase from the first commit without passing the
|
// we can't start an interactive rebase from the first commit without passing the
|
||||||
// '--root' arg
|
// '--root' arg
|
||||||
func getBaseShaOrRoot(commits []*models.Commit, index int) string {
|
func getBaseShaOrRoot(commits []*models.Commit, index int) string {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ func TestRebaseRebaseBranch(t *testing.T) {
|
|||||||
// environment variables that suppress an interactive editor
|
// environment variables that suppress an interactive editor
|
||||||
func TestRebaseSkipEditorCommand(t *testing.T) {
|
func TestRebaseSkipEditorCommand(t *testing.T) {
|
||||||
cmdArgs := []string{"git", "blah"}
|
cmdArgs := []string{"git", "blah"}
|
||||||
runner := oscommands.NewFakeRunner(t).ExpectFunc(func(cmdObj oscommands.ICmdObj) (string, error) {
|
runner := oscommands.NewFakeRunner(t).ExpectFunc("matches editor env var", func(cmdObj oscommands.ICmdObj) bool {
|
||||||
assert.EqualValues(t, cmdArgs, cmdObj.Args())
|
assert.EqualValues(t, cmdArgs, cmdObj.Args())
|
||||||
envVars := cmdObj.GetEnvVars()
|
envVars := cmdObj.GetEnvVars()
|
||||||
for _, regexStr := range []string{
|
for _, regexStr := range []string{
|
||||||
@@ -94,11 +94,11 @@ func TestRebaseSkipEditorCommand(t *testing.T) {
|
|||||||
return regexp.MustCompile(regexStr).MatchString(envVar)
|
return regexp.MustCompile(regexStr).MatchString(envVar)
|
||||||
})
|
})
|
||||||
if !foundMatch {
|
if !foundMatch {
|
||||||
t.Errorf("expected environment variable %s to be set", regexStr)
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "", nil
|
return true
|
||||||
})
|
}, "", nil)
|
||||||
instance := buildRebaseCommands(commonDeps{runner: runner})
|
instance := buildRebaseCommands(commonDeps{runner: runner})
|
||||||
err := instance.runSkipEditorCommand(instance.cmd.New(cmdArgs))
|
err := instance.runSkipEditorCommand(instance.cmd.New(cmdArgs))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -35,34 +35,19 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit
|
|||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
cmdObj := self.cmd.New(cmdArgs).DontLog()
|
cmdObj := self.cmd.New(cmdArgs).DontLog()
|
||||||
|
|
||||||
onlyObtainedNewReflogCommits := false
|
onlyObtainedNewReflogCommits := false
|
||||||
err := cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
err := cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
||||||
fields := strings.SplitN(line, "\x00", 4)
|
commit, ok := self.parseLine(line)
|
||||||
if len(fields) <= 3 {
|
if !ok {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
unixTimestamp, _ := strconv.Atoi(fields[1])
|
|
||||||
|
|
||||||
parentHashes := fields[3]
|
|
||||||
parents := []string{}
|
|
||||||
if len(parentHashes) > 0 {
|
|
||||||
parents = strings.Split(parentHashes, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
commit := &models.Commit{
|
|
||||||
Sha: fields[0],
|
|
||||||
Name: fields[2],
|
|
||||||
UnixTimestamp: int64(unixTimestamp),
|
|
||||||
Status: models.StatusReflog,
|
|
||||||
Parents: parents,
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that the unix timestamp here is the timestamp of the COMMIT, not the reflog entry itself,
|
// note that the unix timestamp here is the timestamp of the COMMIT, not the reflog entry itself,
|
||||||
// so two consecutive reflog entries may have both the same SHA and therefore same timestamp.
|
// so two consecutive reflog entries may have both the same SHA and therefore same timestamp.
|
||||||
// We use the reflog message to disambiguate, and fingers crossed that we never see the same of those
|
// We use the reflog message to disambiguate, and fingers crossed that we never see the same of those
|
||||||
// twice in a row. Reason being that it would mean we'd be erroneously exiting early.
|
// twice in a row. Reason being that it would mean we'd be erroneously exiting early.
|
||||||
if lastReflogCommit != nil && commit.Sha == lastReflogCommit.Sha && commit.UnixTimestamp == lastReflogCommit.UnixTimestamp && commit.Name == lastReflogCommit.Name {
|
if lastReflogCommit != nil && self.sameReflogCommit(commit, lastReflogCommit) {
|
||||||
onlyObtainedNewReflogCommits = true
|
onlyObtainedNewReflogCommits = true
|
||||||
// after this point we already have these reflogs loaded so we'll simply return the new ones
|
// after this point we already have these reflogs loaded so we'll simply return the new ones
|
||||||
return true, nil
|
return true, nil
|
||||||
@@ -77,3 +62,30 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit
|
|||||||
|
|
||||||
return commits, onlyObtainedNewReflogCommits, nil
|
return commits, onlyObtainedNewReflogCommits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ReflogCommitLoader) sameReflogCommit(a *models.Commit, b *models.Commit) bool {
|
||||||
|
return a.Sha == b.Sha && a.UnixTimestamp == b.UnixTimestamp && a.Name == b.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ReflogCommitLoader) parseLine(line string) (*models.Commit, bool) {
|
||||||
|
fields := strings.SplitN(line, "\x00", 4)
|
||||||
|
if len(fields) <= 3 {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
unixTimestamp, _ := strconv.Atoi(fields[1])
|
||||||
|
|
||||||
|
parentHashes := fields[3]
|
||||||
|
parents := []string{}
|
||||||
|
if len(parentHashes) > 0 {
|
||||||
|
parents = strings.Split(parentHashes, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &models.Commit{
|
||||||
|
Sha: fields[0],
|
||||||
|
Name: fields[2],
|
||||||
|
UnixTimestamp: int64(unixTimestamp),
|
||||||
|
Status: models.StatusReflog,
|
||||||
|
Parents: parents,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package git_commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
)
|
)
|
||||||
@@ -53,7 +54,15 @@ func (self *RemoteCommands) DeleteRemoteBranch(task gocui.Task, remoteName strin
|
|||||||
Arg(remoteName, "--delete", branchName).
|
Arg(remoteName, "--delete", branchName).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run()
|
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *RemoteCommands) DeleteRemoteTag(task gocui.Task, remoteName string, tagName string) error {
|
||||||
|
cmdArgs := NewGitCmd("push").
|
||||||
|
Arg(remoteName, "--delete", tagName).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckRemoteBranchExists Returns remote branch
|
// CheckRemoteBranchExists Returns remote branch
|
||||||
@@ -66,3 +75,14 @@ func (self *RemoteCommands) CheckRemoteBranchExists(branchName string) bool {
|
|||||||
|
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve what might be a aliased URL into a full URL
|
||||||
|
// SEE: `man -P 'less +/--get-url +n' git-ls-remote`
|
||||||
|
func (self *RemoteCommands) GetRemoteURL(remoteName string) (string, error) {
|
||||||
|
cmdArgs := NewGitCmd("ls-remote").
|
||||||
|
Arg("--get-url", remoteName).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
url, err := self.cmd.New(cmdArgs).RunWithOutput()
|
||||||
|
return strings.TrimSpace(url), err
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ package git_commands
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
gogit "github.com/jesseduffield/go-git/v5"
|
gogit "github.com/jesseduffield/go-git/v5"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RemoteLoader struct {
|
type RemoteLoader struct {
|
||||||
@@ -31,29 +33,31 @@ func NewRemoteLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemoteLoader) GetRemotes() ([]*models.Remote, error) {
|
func (self *RemoteLoader) GetRemotes() ([]*models.Remote, error) {
|
||||||
cmdArgs := NewGitCmd("branch").Arg("-r").ToArgv()
|
wg := sync.WaitGroup{}
|
||||||
remoteBranchesStr, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
wg.Add(1)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
var remoteBranchesByRemoteName map[string][]*models.RemoteBranch
|
||||||
}
|
var remoteBranchesErr error
|
||||||
|
go utils.Safe(func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
remoteBranchesByRemoteName, remoteBranchesErr = self.getRemoteBranchesByRemoteName()
|
||||||
|
})
|
||||||
|
|
||||||
goGitRemotes, err := self.getGoGitRemotes()
|
goGitRemotes, err := self.getGoGitRemotes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// first step is to get our remotes from go-git
|
wg.Wait()
|
||||||
remotes := slices.Map(goGitRemotes, func(goGitRemote *gogit.Remote) *models.Remote {
|
|
||||||
remoteName := goGitRemote.Config().Name
|
|
||||||
|
|
||||||
re := regexp.MustCompile(fmt.Sprintf(`(?m)^\s*%s\/([\S]+)`, regexp.QuoteMeta(remoteName)))
|
if remoteBranchesErr != nil {
|
||||||
matches := re.FindAllStringSubmatch(remoteBranchesStr, -1)
|
return nil, remoteBranchesErr
|
||||||
branches := slices.Map(matches, func(match []string) *models.RemoteBranch {
|
}
|
||||||
return &models.RemoteBranch{
|
|
||||||
Name: match[1],
|
remotes := lo.Map(goGitRemotes, func(goGitRemote *gogit.Remote, _ int) *models.Remote {
|
||||||
RemoteName: remoteName,
|
remoteName := goGitRemote.Config().Name
|
||||||
}
|
branches := remoteBranchesByRemoteName[remoteName]
|
||||||
})
|
|
||||||
|
|
||||||
return &models.Remote{
|
return &models.Remote{
|
||||||
Name: goGitRemote.Config().Name,
|
Name: goGitRemote.Config().Name,
|
||||||
@@ -76,3 +80,51 @@ func (self *RemoteLoader) GetRemotes() ([]*models.Remote, error) {
|
|||||||
|
|
||||||
return remotes, nil
|
return remotes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RemoteLoader) getRemoteBranchesByRemoteName() (map[string][]*models.RemoteBranch, error) {
|
||||||
|
remoteBranchesByRemoteName := make(map[string][]*models.RemoteBranch)
|
||||||
|
|
||||||
|
var sortOrder string
|
||||||
|
switch strings.ToLower(self.AppState.RemoteBranchSortOrder) {
|
||||||
|
case "alphabetical":
|
||||||
|
sortOrder = "refname"
|
||||||
|
case "date":
|
||||||
|
sortOrder = "-committerdate"
|
||||||
|
default:
|
||||||
|
sortOrder = "refname"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdArgs := NewGitCmd("for-each-ref").
|
||||||
|
Arg(fmt.Sprintf("--sort=%s", sortOrder)).
|
||||||
|
Arg("--format=%(refname:short)").
|
||||||
|
Arg("refs/remotes").
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
err := self.cmd.New(cmdArgs).DontLog().RunAndProcessLines(func(line string) (bool, error) {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
|
||||||
|
split := strings.SplitN(line, "/", 2)
|
||||||
|
if len(split) != 2 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
remoteName := split[0]
|
||||||
|
name := split[1]
|
||||||
|
|
||||||
|
_, ok := remoteBranchesByRemoteName[remoteName]
|
||||||
|
if !ok {
|
||||||
|
remoteBranchesByRemoteName[remoteName] = []*models.RemoteBranch{}
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteBranchesByRemoteName[remoteName] = append(remoteBranchesByRemoteName[remoteName],
|
||||||
|
&models.RemoteBranch{
|
||||||
|
Name: name,
|
||||||
|
RemoteName: remoteName,
|
||||||
|
})
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return remoteBranchesByRemoteName, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package git_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
ioFs "io/fs"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RepoPaths struct {
|
||||||
|
worktreePath string
|
||||||
|
worktreeGitDirPath string
|
||||||
|
repoPath string
|
||||||
|
repoGitDirPath string
|
||||||
|
repoName string
|
||||||
|
}
|
||||||
|
|
||||||
|
var gitPathFormatVersion GitVersion = GitVersion{2, 31, 0, ""}
|
||||||
|
|
||||||
|
// Path to the current worktree. If we're in the main worktree, this will
|
||||||
|
// be the same as RepoPath()
|
||||||
|
func (self *RepoPaths) WorktreePath() string {
|
||||||
|
return self.worktreePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path of the worktree's git dir.
|
||||||
|
// If we're in the main worktree, this will be the .git dir under the RepoPath().
|
||||||
|
// If we're in a linked worktree, it will be the directory pointed at by the worktree's .git file
|
||||||
|
func (self *RepoPaths) WorktreeGitDirPath() string {
|
||||||
|
return self.worktreeGitDirPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path of the repo. If we're in a the main worktree, this will be the same as WorktreePath()
|
||||||
|
// If we're in a bare repo, it will be the parent folder of the bare repo
|
||||||
|
func (self *RepoPaths) RepoPath() string {
|
||||||
|
return self.repoPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// path of the git-dir for the repo.
|
||||||
|
// If this is a bare repo, it will be the location of the bare repo
|
||||||
|
// If this is a non-bare repo, it will be the location of the .git dir in
|
||||||
|
// the main worktree.
|
||||||
|
func (self *RepoPaths) RepoGitDirPath() string {
|
||||||
|
return self.repoGitDirPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name of the repo. Basename of the folder containing the repo.
|
||||||
|
func (self *RepoPaths) RepoName() string {
|
||||||
|
return self.repoName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the repo paths for a typical repo
|
||||||
|
func MockRepoPaths(currentPath string) *RepoPaths {
|
||||||
|
return &RepoPaths{
|
||||||
|
worktreePath: currentPath,
|
||||||
|
worktreeGitDirPath: path.Join(currentPath, ".git"),
|
||||||
|
repoPath: currentPath,
|
||||||
|
repoGitDirPath: path.Join(currentPath, ".git"),
|
||||||
|
repoName: "lazygit",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRepoPaths(
|
||||||
|
cmd oscommands.ICmdObjBuilder,
|
||||||
|
version *GitVersion,
|
||||||
|
) (*RepoPaths, error) {
|
||||||
|
gitDirOutput, err := callGitRevParse(cmd, version, "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gitDirResults := strings.Split(utils.NormalizeLinefeeds(gitDirOutput), "\n")
|
||||||
|
worktreePath := gitDirResults[0]
|
||||||
|
worktreeGitDirPath := gitDirResults[1]
|
||||||
|
repoGitDirPath := gitDirResults[2]
|
||||||
|
if version.IsOlderThanVersion(&gitPathFormatVersion) {
|
||||||
|
repoGitDirPath, err = filepath.Abs(repoGitDirPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're in a submodule, --show-superproject-working-tree will return
|
||||||
|
// a value, meaning gitDirResults will be length 4. In that case
|
||||||
|
// return the worktree path as the repoPath. Otherwise we're in a
|
||||||
|
// normal repo or a worktree so return the parent of the git common
|
||||||
|
// dir (repoGitDirPath)
|
||||||
|
isSubmodule := len(gitDirResults) == 4
|
||||||
|
|
||||||
|
var repoPath string
|
||||||
|
if isSubmodule {
|
||||||
|
repoPath = worktreePath
|
||||||
|
} else {
|
||||||
|
repoPath = path.Dir(repoGitDirPath)
|
||||||
|
}
|
||||||
|
repoName := path.Base(repoPath)
|
||||||
|
|
||||||
|
return &RepoPaths{
|
||||||
|
worktreePath: worktreePath,
|
||||||
|
worktreeGitDirPath: worktreeGitDirPath,
|
||||||
|
repoPath: repoPath,
|
||||||
|
repoGitDirPath: repoGitDirPath,
|
||||||
|
repoName: repoName,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callGitRevParse(
|
||||||
|
cmd oscommands.ICmdObjBuilder,
|
||||||
|
version *GitVersion,
|
||||||
|
gitRevArgs ...string,
|
||||||
|
) (string, error) {
|
||||||
|
return callGitRevParseWithDir(cmd, version, "", gitRevArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func callGitRevParseWithDir(
|
||||||
|
cmd oscommands.ICmdObjBuilder,
|
||||||
|
version *GitVersion,
|
||||||
|
dir string,
|
||||||
|
gitRevArgs ...string,
|
||||||
|
) (string, error) {
|
||||||
|
gitRevParse := NewGitCmd("rev-parse").ArgIf(version.IsAtLeastVersion(&gitPathFormatVersion), "--path-format=absolute").Arg(gitRevArgs...)
|
||||||
|
if dir != "" {
|
||||||
|
gitRevParse.Dir(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
gitCmd := cmd.New(gitRevParse.ToArgv()).DontLog()
|
||||||
|
res, err := gitCmd.RunWithOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Errorf("'%s' failed: %v", gitCmd.ToString(), err)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(res), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the paths of linked worktrees
|
||||||
|
func linkedWortkreePaths(fs afero.Fs, repoGitDirPath string) []string {
|
||||||
|
result := []string{}
|
||||||
|
// For each directory in this path we're going to cat the `gitdir` file and append its contents to our result
|
||||||
|
// That file points us to the `.git` file in the worktree.
|
||||||
|
worktreeGitDirsPath := path.Join(repoGitDirPath, "worktrees")
|
||||||
|
|
||||||
|
// ensure the directory exists
|
||||||
|
_, err := fs.Stat(worktreeGitDirsPath)
|
||||||
|
if err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = afero.Walk(fs, worktreeGitDirsPath, func(currPath string, info ioFs.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
gitDirPath := path.Join(currPath, "gitdir")
|
||||||
|
gitDirBytes, err := afero.ReadFile(fs, gitDirPath)
|
||||||
|
if err != nil {
|
||||||
|
// ignoring error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
trimmedGitDir := strings.TrimSpace(string(gitDirBytes))
|
||||||
|
// removing the .git part
|
||||||
|
worktreeDir := path.Dir(trimmedGitDir)
|
||||||
|
result = append(result, worktreeDir)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package git_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
argFn func() []string
|
||||||
|
errFn func(getRevParseArgs argFn) error
|
||||||
|
)
|
||||||
|
|
||||||
|
type Scenario struct {
|
||||||
|
Name string
|
||||||
|
BeforeFunc func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn)
|
||||||
|
Path string
|
||||||
|
Expected *RepoPaths
|
||||||
|
Err errFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetRepoPaths(t *testing.T) {
|
||||||
|
scenarios := []Scenario{
|
||||||
|
{
|
||||||
|
Name: "typical case",
|
||||||
|
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||||
|
// setup for main worktree
|
||||||
|
expectedOutput := []string{
|
||||||
|
// --show-toplevel
|
||||||
|
"/path/to/repo",
|
||||||
|
// --git-dir
|
||||||
|
"/path/to/repo/.git",
|
||||||
|
// --git-common-dir
|
||||||
|
"/path/to/repo/.git",
|
||||||
|
// --show-superproject-working-tree
|
||||||
|
}
|
||||||
|
runner.ExpectGitArgs(
|
||||||
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
|
||||||
|
strings.Join(expectedOutput, "\n"),
|
||||||
|
nil)
|
||||||
|
},
|
||||||
|
Path: "/path/to/repo",
|
||||||
|
Expected: &RepoPaths{
|
||||||
|
worktreePath: "/path/to/repo",
|
||||||
|
worktreeGitDirPath: "/path/to/repo/.git",
|
||||||
|
repoPath: "/path/to/repo",
|
||||||
|
repoGitDirPath: "/path/to/repo/.git",
|
||||||
|
repoName: "repo",
|
||||||
|
},
|
||||||
|
Err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "submodule",
|
||||||
|
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||||
|
expectedOutput := []string{
|
||||||
|
// --show-toplevel
|
||||||
|
"/path/to/repo/submodule1",
|
||||||
|
// --git-dir
|
||||||
|
"/path/to/repo/.git/modules/submodule1",
|
||||||
|
// --git-common-dir
|
||||||
|
"/path/to/repo/.git/modules/submodule1",
|
||||||
|
// --show-superproject-working-tree
|
||||||
|
"/path/to/repo",
|
||||||
|
}
|
||||||
|
runner.ExpectGitArgs(
|
||||||
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
|
||||||
|
strings.Join(expectedOutput, "\n"),
|
||||||
|
nil)
|
||||||
|
},
|
||||||
|
Path: "/path/to/repo/submodule1",
|
||||||
|
Expected: &RepoPaths{
|
||||||
|
worktreePath: "/path/to/repo/submodule1",
|
||||||
|
worktreeGitDirPath: "/path/to/repo/.git/modules/submodule1",
|
||||||
|
repoPath: "/path/to/repo/submodule1",
|
||||||
|
repoGitDirPath: "/path/to/repo/.git/modules/submodule1",
|
||||||
|
repoName: "submodule1",
|
||||||
|
},
|
||||||
|
Err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "git rev-parse returns an error",
|
||||||
|
BeforeFunc: func(runner *oscommands.FakeCmdObjRunner, getRevParseArgs argFn) {
|
||||||
|
runner.ExpectGitArgs(
|
||||||
|
append(getRevParseArgs(), "--show-toplevel", "--absolute-git-dir", "--git-common-dir", "--show-superproject-working-tree"),
|
||||||
|
"",
|
||||||
|
errors.New("fatal: invalid gitfile format: /path/to/repo/worktree2/.git"))
|
||||||
|
},
|
||||||
|
Path: "/path/to/repo/worktree2",
|
||||||
|
Expected: nil,
|
||||||
|
Err: func(getRevParseArgs argFn) error {
|
||||||
|
args := strings.Join(getRevParseArgs(), " ")
|
||||||
|
return errors.New(
|
||||||
|
fmt.Sprintf("'git %v --show-toplevel --absolute-git-dir --git-common-dir --show-superproject-working-tree' failed: fatal: invalid gitfile format: /path/to/repo/worktree2/.git", args),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
s := s
|
||||||
|
t.Run(s.Name, func(t *testing.T) {
|
||||||
|
runner := oscommands.NewFakeRunner(t)
|
||||||
|
cmd := oscommands.NewDummyCmdObjBuilder(runner)
|
||||||
|
|
||||||
|
version, err := GetGitVersion(oscommands.NewDummyOSCommand())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
getRevParseArgs := func() []string {
|
||||||
|
args := []string{"rev-parse"}
|
||||||
|
if version.IsAtLeast(2, 31, 0) {
|
||||||
|
args = append(args, "--path-format=absolute")
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
// prepare the filesystem for the scenario
|
||||||
|
s.BeforeFunc(runner, getRevParseArgs)
|
||||||
|
|
||||||
|
repoPaths, err := GetRepoPaths(cmd, version)
|
||||||
|
|
||||||
|
// check the error and the paths
|
||||||
|
if s.Err != nil {
|
||||||
|
scenarioErr := s.Err(getRevParseArgs)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.EqualError(t, err, scenarioErr.Error())
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, s.Expected, repoPaths)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,14 +80,15 @@ func (self *StashCommands) Sha(index int) (string, error) {
|
|||||||
return strings.Trim(sha, "\r\n"), err
|
return strings.Trim(sha, "\r\n"), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StashCommands) ShowStashEntryCmdObj(index int, ignoreWhitespace bool) oscommands.ICmdObj {
|
func (self *StashCommands) ShowStashEntryCmdObj(index int) oscommands.ICmdObj {
|
||||||
cmdArgs := NewGitCmd("stash").Arg("show").
|
cmdArgs := NewGitCmd("stash").Arg("show").
|
||||||
Arg("-p").
|
Arg("-p").
|
||||||
Arg("--stat").
|
Arg("--stat").
|
||||||
Arg(fmt.Sprintf("--color=%s", self.UserConfig.Git.Paging.ColorArg)).
|
Arg(fmt.Sprintf("--color=%s", self.UserConfig.Git.Paging.ColorArg)).
|
||||||
Arg(fmt.Sprintf("--unified=%d", self.UserConfig.Git.DiffContextSize)).
|
Arg(fmt.Sprintf("--unified=%d", self.AppState.DiffContextSize)).
|
||||||
ArgIf(ignoreWhitespace, "--ignore-all-space").
|
ArgIf(self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||||
Arg(fmt.Sprintf("stash@{%d}", index)).
|
Arg(fmt.Sprintf("stash@{%d}", index)).
|
||||||
|
Dir(self.repoPaths.worktreePath).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StashLoader struct {
|
type StashLoader struct {
|
||||||
@@ -32,14 +32,14 @@ func (self *StashLoader) GetStashEntries(filterPath string) []*models.StashEntry
|
|||||||
return self.getUnfilteredStashEntries()
|
return self.getUnfilteredStashEntries()
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("stash").Arg("list", "--name-only").ToArgv()
|
cmdArgs := NewGitCmd("stash").Arg("list", "-z", "--name-only", "--pretty=%ct|%gs").ToArgv()
|
||||||
rawString, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
rawString, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return self.getUnfilteredStashEntries()
|
return self.getUnfilteredStashEntries()
|
||||||
}
|
}
|
||||||
stashEntries := []*models.StashEntry{}
|
stashEntries := []*models.StashEntry{}
|
||||||
var currentStashEntry *models.StashEntry
|
var currentStashEntry *models.StashEntry
|
||||||
lines := utils.SplitLines(rawString)
|
lines := utils.SplitNul(rawString)
|
||||||
isAStash := func(line string) bool { return strings.HasPrefix(line, "stash@{") }
|
isAStash := func(line string) bool { return strings.HasPrefix(line, "stash@{") }
|
||||||
re := regexp.MustCompile(`stash@\{(\d+)\}`)
|
re := regexp.MustCompile(`stash@\{(\d+)\}`)
|
||||||
|
|
||||||
@@ -66,17 +66,32 @@ outer:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *StashLoader) getUnfilteredStashEntries() []*models.StashEntry {
|
func (self *StashLoader) getUnfilteredStashEntries() []*models.StashEntry {
|
||||||
cmdArgs := NewGitCmd("stash").Arg("list", "-z", "--pretty=%gs").ToArgv()
|
cmdArgs := NewGitCmd("stash").Arg("list", "-z", "--pretty=%ct|%gs").ToArgv()
|
||||||
|
|
||||||
rawString, _ := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
rawString, _ := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
return slices.MapWithIndex(utils.SplitNul(rawString), func(line string, index int) *models.StashEntry {
|
return lo.Map(utils.SplitNul(rawString), func(line string, index int) *models.StashEntry {
|
||||||
return self.stashEntryFromLine(line, index)
|
return self.stashEntryFromLine(line, index)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StashLoader) stashEntryFromLine(line string, index int) *models.StashEntry {
|
func (c *StashLoader) stashEntryFromLine(line string, index int) *models.StashEntry {
|
||||||
return &models.StashEntry{
|
model := &models.StashEntry{
|
||||||
Name: line,
|
Name: line,
|
||||||
Index: index,
|
Index: index,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tstr, msg, ok := strings.Cut(line, "|")
|
||||||
|
if !ok {
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := strconv.ParseInt(tstr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Name = msg
|
||||||
|
model.Recency = utils.UnixToTimeAgo(t)
|
||||||
|
|
||||||
|
return model
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ func TestGetStashEntries(t *testing.T) {
|
|||||||
"No stash entries found",
|
"No stash entries found",
|
||||||
"",
|
"",
|
||||||
oscommands.NewFakeRunner(t).
|
oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"stash", "list", "-z", "--pretty=%gs"}, "", nil),
|
ExpectGitArgs([]string{"stash", "list", "-z", "--pretty=%ct|%gs"}, "", nil),
|
||||||
[]*models.StashEntry{},
|
[]*models.StashEntry{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Several stash entries found",
|
"Several stash entries found",
|
||||||
"",
|
"",
|
||||||
oscommands.NewFakeRunner(t).
|
oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"stash", "list", "-z", "--pretty=%gs"},
|
ExpectGitArgs([]string{"stash", "list", "-z", "--pretty=%ct|%gs"},
|
||||||
"WIP on add-pkg-commands-test: 55c6af2 increase parallel build\x00WIP on master: bb86a3f update github template\x00",
|
"WIP on add-pkg-commands-test: 55c6af2 increase parallel build\x00WIP on master: bb86a3f update github template\x00",
|
||||||
nil,
|
nil,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -112,21 +112,21 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||||||
index: 5,
|
index: 5,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
expected: []string{"git", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "stash@{5}"},
|
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "stash@{5}"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Show diff with custom context size",
|
testName: "Show diff with custom context size",
|
||||||
index: 5,
|
index: 5,
|
||||||
contextSize: 77,
|
contextSize: 77,
|
||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
expected: []string{"git", "stash", "show", "-p", "--stat", "--color=always", "--unified=77", "stash@{5}"},
|
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "--color=always", "--unified=77", "stash@{5}"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Default case",
|
testName: "Default case",
|
||||||
index: 5,
|
index: 5,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
ignoreWhitespace: true,
|
ignoreWhitespace: true,
|
||||||
expected: []string{"git", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "--ignore-all-space", "stash@{5}"},
|
expected: []string{"git", "-C", "/path/to/worktree", "stash", "show", "-p", "--stat", "--color=always", "--unified=3", "--ignore-all-space", "stash@{5}"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,10 +134,15 @@ func TestStashStashEntryCmdObj(t *testing.T) {
|
|||||||
s := s
|
s := s
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
userConfig := config.GetDefaultConfig()
|
userConfig := config.GetDefaultConfig()
|
||||||
userConfig.Git.DiffContextSize = s.contextSize
|
appState := &config.AppState{}
|
||||||
instance := buildStashCommands(commonDeps{userConfig: userConfig})
|
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
|
||||||
|
appState.DiffContextSize = s.contextSize
|
||||||
|
repoPaths := RepoPaths{
|
||||||
|
worktreePath: "/path/to/worktree",
|
||||||
|
}
|
||||||
|
instance := buildStashCommands(commonDeps{userConfig: userConfig, appState: appState, repoPaths: &repoPaths})
|
||||||
|
|
||||||
cmdStr := instance.ShowStashEntryCmdObj(s.index, s.ignoreWhitespace).Args()
|
cmdStr := instance.ShowStashEntryCmdObj(s.index).Args()
|
||||||
assert.Equal(t, s.expected, cmdStr)
|
assert.Equal(t, s.expected, cmdStr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package git_commands
|
package git_commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -24,19 +25,16 @@ func NewStatusCommands(
|
|||||||
// RebaseMode returns "" for non-rebase mode, "normal" for normal rebase
|
// RebaseMode returns "" for non-rebase mode, "normal" for normal rebase
|
||||||
// and "interactive" for interactive rebase
|
// and "interactive" for interactive rebase
|
||||||
func (self *StatusCommands) RebaseMode() (enums.RebaseMode, error) {
|
func (self *StatusCommands) RebaseMode() (enums.RebaseMode, error) {
|
||||||
exists, err := self.os.FileExists(filepath.Join(self.dotGitDir, "rebase-apply"))
|
ok, err := self.IsInNormalRebase()
|
||||||
if err != nil {
|
if err == nil && ok {
|
||||||
return enums.REBASE_MODE_NONE, err
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
return enums.REBASE_MODE_NORMAL, nil
|
return enums.REBASE_MODE_NORMAL, nil
|
||||||
}
|
}
|
||||||
exists, err = self.os.FileExists(filepath.Join(self.dotGitDir, "rebase-merge"))
|
ok, err = self.IsInInteractiveRebase()
|
||||||
if exists {
|
if err == nil && ok {
|
||||||
return enums.REBASE_MODE_INTERACTIVE, err
|
return enums.REBASE_MODE_INTERACTIVE, err
|
||||||
} else {
|
|
||||||
return enums.REBASE_MODE_NONE, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return enums.REBASE_MODE_NONE, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StatusCommands) WorkingTreeState() enums.RebaseMode {
|
func (self *StatusCommands) WorkingTreeState() enums.RebaseMode {
|
||||||
@@ -67,7 +65,26 @@ func IsBareRepo(osCommand *oscommands.OSCommand) (bool, error) {
|
|||||||
return strconv.ParseBool(strings.TrimSpace(res))
|
return strconv.ParseBool(strings.TrimSpace(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *StatusCommands) IsInNormalRebase() (bool, error) {
|
||||||
|
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-apply"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *StatusCommands) IsInInteractiveRebase() (bool, error) {
|
||||||
|
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "rebase-merge"))
|
||||||
|
}
|
||||||
|
|
||||||
// IsInMergeState states whether we are still mid-merge
|
// IsInMergeState states whether we are still mid-merge
|
||||||
func (self *StatusCommands) IsInMergeState() (bool, error) {
|
func (self *StatusCommands) IsInMergeState() (bool, error) {
|
||||||
return self.os.FileExists(filepath.Join(self.dotGitDir, "MERGE_HEAD"))
|
return self.os.FileExists(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "MERGE_HEAD"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Full ref (e.g. "refs/heads/mybranch") of the branch that is currently
|
||||||
|
// being rebased, or empty string when we're not in a rebase
|
||||||
|
func (self *StatusCommands) BranchBeingRebased() string {
|
||||||
|
for _, dir := range []string{"rebase-merge", "rebase-apply"} {
|
||||||
|
if bytesContent, err := os.ReadFile(filepath.Join(self.repoPaths.WorktreeGitDirPath(), dir, "head-name")); err == nil {
|
||||||
|
return strings.TrimSpace(string(bytesContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func (self *SubmoduleCommands) Stash(submodule *models.SubmoduleConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("stash").
|
cmdArgs := NewGitCmd("stash").
|
||||||
RepoPath(submodule.Path).
|
Dir(submodule.Path).
|
||||||
Arg("--include-untracked").
|
Arg("--include-untracked").
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
@@ -139,7 +139,9 @@ func (self *SubmoduleCommands) Delete(submodule *models.SubmoduleConfig) error {
|
|||||||
self.Log.Error(err)
|
self.Log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.RemoveAll(filepath.Join(self.dotGitDir, "modules", submodule.Path))
|
// We may in fact want to use the repo's git dir path but git docs say not to
|
||||||
|
// mix submodules and worktrees anyway.
|
||||||
|
return os.RemoveAll(filepath.Join(self.repoPaths.WorktreeGitDirPath(), "modules", submodule.Path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubmoduleCommands) Add(name string, path string, url string) error {
|
func (self *SubmoduleCommands) Add(name string, path string, url string) error {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func (self *SyncCommands) PushCmdObj(task gocui.Task, opts PushOpts) (oscommands
|
|||||||
ArgIf(opts.UpstreamBranch != "", opts.UpstreamBranch).
|
ArgIf(opts.UpstreamBranch != "", opts.UpstreamBranch).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
cmdObj := self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).WithMutex(self.syncMutex)
|
cmdObj := self.cmd.New(cmdArgs).PromptOnCredentialRequest(task)
|
||||||
return cmdObj, nil
|
return cmdObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,10 +49,16 @@ func (self *SyncCommands) Push(task gocui.Task, opts PushOpts) error {
|
|||||||
return cmdObj.Run()
|
return cmdObj.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *SyncCommands) fetchCommandBuilder(fetchAll bool) *GitCommandBuilder {
|
||||||
|
return NewGitCmd("fetch").
|
||||||
|
ArgIf(fetchAll, "--all").
|
||||||
|
// avoid writing to .git/FETCH_HEAD; this allows running a pull
|
||||||
|
// concurrently without getting errors
|
||||||
|
ArgIf(self.version.IsAtLeast(2, 29, 0), "--no-write-fetch-head")
|
||||||
|
}
|
||||||
|
|
||||||
func (self *SyncCommands) FetchCmdObj(task gocui.Task) oscommands.ICmdObj {
|
func (self *SyncCommands) FetchCmdObj(task gocui.Task) oscommands.ICmdObj {
|
||||||
cmdArgs := NewGitCmd("fetch").
|
cmdArgs := self.fetchCommandBuilder(self.UserConfig.Git.FetchAll).ToArgv()
|
||||||
ArgIf(self.UserConfig.Git.FetchAll, "--all").
|
|
||||||
ToArgv()
|
|
||||||
|
|
||||||
cmdObj := self.cmd.New(cmdArgs)
|
cmdObj := self.cmd.New(cmdArgs)
|
||||||
cmdObj.PromptOnCredentialRequest(task)
|
cmdObj.PromptOnCredentialRequest(task)
|
||||||
@@ -64,13 +70,10 @@ func (self *SyncCommands) Fetch(task gocui.Task) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *SyncCommands) FetchBackgroundCmdObj() oscommands.ICmdObj {
|
func (self *SyncCommands) FetchBackgroundCmdObj() oscommands.ICmdObj {
|
||||||
cmdArgs := NewGitCmd("fetch").
|
cmdArgs := self.fetchCommandBuilder(self.UserConfig.Git.FetchAll).ToArgv()
|
||||||
ArgIf(self.UserConfig.Git.FetchAll, "--all").
|
|
||||||
ToArgv()
|
|
||||||
|
|
||||||
cmdObj := self.cmd.New(cmdArgs)
|
cmdObj := self.cmd.New(cmdArgs)
|
||||||
cmdObj.DontLog().FailOnCredentialRequest()
|
cmdObj.DontLog().FailOnCredentialRequest()
|
||||||
cmdObj.WithMutex(self.syncMutex)
|
|
||||||
return cmdObj
|
return cmdObj
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,6 +85,7 @@ type PullOptions struct {
|
|||||||
RemoteName string
|
RemoteName string
|
||||||
BranchName string
|
BranchName string
|
||||||
FastForwardOnly bool
|
FastForwardOnly bool
|
||||||
|
WorktreeGitDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error {
|
func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error {
|
||||||
@@ -90,26 +94,32 @@ func (self *SyncCommands) Pull(task gocui.Task, opts PullOptions) error {
|
|||||||
ArgIf(opts.FastForwardOnly, "--ff-only").
|
ArgIf(opts.FastForwardOnly, "--ff-only").
|
||||||
ArgIf(opts.RemoteName != "", opts.RemoteName).
|
ArgIf(opts.RemoteName != "", opts.RemoteName).
|
||||||
ArgIf(opts.BranchName != "", opts.BranchName).
|
ArgIf(opts.BranchName != "", opts.BranchName).
|
||||||
|
GitDirIf(opts.WorktreeGitDir != "", opts.WorktreeGitDir).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
// setting GIT_SEQUENCE_EDITOR to ':' as a way of skipping it, in case the user
|
// setting GIT_SEQUENCE_EDITOR to ':' as a way of skipping it, in case the user
|
||||||
// has 'pull.rebase = interactive' configured.
|
// has 'pull.rebase = interactive' configured.
|
||||||
return self.cmd.New(cmdArgs).AddEnvVars("GIT_SEQUENCE_EDITOR=:").PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run()
|
return self.cmd.New(cmdArgs).AddEnvVars("GIT_SEQUENCE_EDITOR=:").PromptOnCredentialRequest(task).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SyncCommands) FastForward(task gocui.Task, branchName string, remoteName string, remoteBranchName string) error {
|
func (self *SyncCommands) FastForward(
|
||||||
cmdArgs := NewGitCmd("fetch").
|
task gocui.Task,
|
||||||
|
branchName string,
|
||||||
|
remoteName string,
|
||||||
|
remoteBranchName string,
|
||||||
|
) error {
|
||||||
|
cmdArgs := self.fetchCommandBuilder(false).
|
||||||
Arg(remoteName).
|
Arg(remoteName).
|
||||||
Arg(remoteBranchName + ":" + branchName).
|
Arg(remoteBranchName + ":" + branchName).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run()
|
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SyncCommands) FetchRemote(task gocui.Task, remoteName string) error {
|
func (self *SyncCommands) FetchRemote(task gocui.Task, remoteName string) error {
|
||||||
cmdArgs := NewGitCmd("fetch").
|
cmdArgs := self.fetchCommandBuilder(false).
|
||||||
Arg(remoteName).
|
Arg(remoteName).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run()
|
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).Run()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,16 +12,19 @@ func NewTagCommands(gitCommon *GitCommon) *TagCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagCommands) CreateLightweight(tagName string, ref string) error {
|
func (self *TagCommands) CreateLightweight(tagName string, ref string, force bool) error {
|
||||||
cmdArgs := NewGitCmd("tag").Arg("--", tagName).
|
cmdArgs := NewGitCmd("tag").
|
||||||
|
ArgIf(force, "--force").
|
||||||
|
Arg("--", tagName).
|
||||||
ArgIf(len(ref) > 0, ref).
|
ArgIf(len(ref) > 0, ref).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).Run()
|
return self.cmd.New(cmdArgs).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagCommands) CreateAnnotated(tagName, ref, msg string) error {
|
func (self *TagCommands) CreateAnnotated(tagName, ref, msg string, force bool) error {
|
||||||
cmdArgs := NewGitCmd("tag").Arg(tagName).
|
cmdArgs := NewGitCmd("tag").Arg(tagName).
|
||||||
|
ArgIf(force, "--force").
|
||||||
ArgIf(len(ref) > 0, ref).
|
ArgIf(len(ref) > 0, ref).
|
||||||
Arg("-m", msg).
|
Arg("-m", msg).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
@@ -29,7 +32,16 @@ func (self *TagCommands) CreateAnnotated(tagName, ref, msg string) error {
|
|||||||
return self.cmd.New(cmdArgs).Run()
|
return self.cmd.New(cmdArgs).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagCommands) Delete(tagName string) error {
|
func (self *TagCommands) HasTag(tagName string) bool {
|
||||||
|
cmdArgs := NewGitCmd("show-ref").
|
||||||
|
Arg("--tags", "--quiet", "--verify", "--").
|
||||||
|
Arg("refs/tags/" + tagName).
|
||||||
|
ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).Run() == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TagCommands) LocalDelete(tagName string) error {
|
||||||
cmdArgs := NewGitCmd("tag").Arg("-d", tagName).
|
cmdArgs := NewGitCmd("tag").Arg("-d", tagName).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
@@ -40,5 +52,5 @@ func (self *TagCommands) Push(task gocui.Task, remoteName string, tagName string
|
|||||||
cmdArgs := NewGitCmd("push").Arg(remoteName, "tag", tagName).
|
cmdArgs := NewGitCmd("push").Arg(remoteName, "tag", tagName).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).WithMutex(self.syncMutex).Run()
|
return self.cmd.New(cmdArgs).PromptOnCredentialRequest(task).Run()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package git_commands
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/common"
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TagLoader struct {
|
type TagLoader struct {
|
||||||
@@ -38,7 +38,7 @@ func (self *TagLoader) GetTags() ([]*models.Tag, error) {
|
|||||||
|
|
||||||
lineRegex := regexp.MustCompile(`^([^\s]+)(\s+)?(.*)$`)
|
lineRegex := regexp.MustCompile(`^([^\s]+)(\s+)?(.*)$`)
|
||||||
|
|
||||||
tags := slices.Map(split, func(line string) *models.Tag {
|
tags := lo.Map(split, func(line string, _ int) *models.Tag {
|
||||||
matches := lineRegex.FindStringSubmatch(line)
|
matches := lineRegex.FindStringSubmatch(line)
|
||||||
tagName := matches[1]
|
tagName := matches[1]
|
||||||
message := ""
|
message := ""
|
||||||
|
|||||||
@@ -69,3 +69,11 @@ func (v *GitVersion) IsOlderThan(major, minor, patch int) bool {
|
|||||||
func (v *GitVersion) IsOlderThanVersion(version *GitVersion) bool {
|
func (v *GitVersion) IsOlderThanVersion(version *GitVersion) bool {
|
||||||
return v.IsOlderThan(version.Major, version.Minor, version.Patch)
|
return v.IsOlderThan(version.Major, version.Minor, version.Patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *GitVersion) IsAtLeast(major, minor, patch int) bool {
|
||||||
|
return !v.IsOlderThan(major, minor, patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *GitVersion) IsAtLeastVersion(version *GitVersion) bool {
|
||||||
|
return v.IsAtLeast(version.Major, version.Minor, version.Patch)
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,3 +45,12 @@ func TestGitVersionIsOlderThan(t *testing.T) {
|
|||||||
assert.True(t, (&GitVersion{2, 0, 1, ""}).IsOlderThan(2, 1, 0))
|
assert.True(t, (&GitVersion{2, 0, 1, ""}).IsOlderThan(2, 1, 0))
|
||||||
assert.True(t, (&GitVersion{2, 0, 1, ""}).IsOlderThan(3, 0, 0))
|
assert.True(t, (&GitVersion{2, 0, 1, ""}).IsOlderThan(3, 0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGitVersionIsAtLeast(t *testing.T) {
|
||||||
|
assert.True(t, (&GitVersion{2, 0, 0, ""}).IsAtLeast(1, 99, 99))
|
||||||
|
assert.True(t, (&GitVersion{2, 0, 0, ""}).IsAtLeast(2, 0, 0))
|
||||||
|
assert.True(t, (&GitVersion{2, 1, 0, ""}).IsAtLeast(2, 0, 9))
|
||||||
|
|
||||||
|
assert.False(t, (&GitVersion{2, 0, 1, ""}).IsAtLeast(2, 1, 0))
|
||||||
|
assert.False(t, (&GitVersion{2, 0, 1, ""}).IsAtLeast(3, 0, 0))
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ func (self *WorkingTreeCommands) OpenMergeToolCmdObj() oscommands.ICmdObj {
|
|||||||
return self.cmd.New(NewGitCmd("mergetool").ToArgv())
|
return self.cmd.New(NewGitCmd("mergetool").ToArgv())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) OpenMergeTool() error {
|
|
||||||
return self.OpenMergeToolCmdObj().Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// StageFile stages a file
|
// StageFile stages a file
|
||||||
func (self *WorkingTreeCommands) StageFile(path string) error {
|
func (self *WorkingTreeCommands) StageFile(path string) error {
|
||||||
return self.StageFiles([]string{path})
|
return self.StageFiles([]string{path})
|
||||||
@@ -61,21 +57,20 @@ func (self *WorkingTreeCommands) UnstageAll() error {
|
|||||||
// UnStageFile unstages a file
|
// UnStageFile unstages a file
|
||||||
// we accept an array of filenames for the cases where a file has been renamed i.e.
|
// we accept an array of filenames for the cases where a file has been renamed i.e.
|
||||||
// we accept the current name and the previous name
|
// we accept the current name and the previous name
|
||||||
func (self *WorkingTreeCommands) UnStageFile(fileNames []string, reset bool) error {
|
func (self *WorkingTreeCommands) UnStageFile(paths []string, tracked bool) error {
|
||||||
for _, name := range fileNames {
|
if tracked {
|
||||||
var cmdArgs []string
|
return self.UnstageTrackedFiles(paths)
|
||||||
if reset {
|
} else {
|
||||||
cmdArgs = NewGitCmd("reset").Arg("HEAD", "--", name).ToArgv()
|
return self.UnstageUntrackedFiles(paths)
|
||||||
} else {
|
|
||||||
cmdArgs = NewGitCmd("rm").Arg("--cached", "--force", "--", name).ToArgv()
|
|
||||||
}
|
|
||||||
|
|
||||||
err := self.cmd.New(cmdArgs).Run()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
func (self *WorkingTreeCommands) UnstageTrackedFiles(paths []string) error {
|
||||||
|
return self.cmd.New(NewGitCmd("reset").Arg("HEAD", "--").Arg(paths...).ToArgv()).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorkingTreeCommands) UnstageUntrackedFiles(paths []string) error {
|
||||||
|
return self.cmd.New(NewGitCmd("rm").Arg("--cached", "--force", "--").Arg(paths...).ToArgv()).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) BeforeAndAfterFileForRename(file *models.File) (*models.File, *models.File, error) {
|
func (self *WorkingTreeCommands) BeforeAndAfterFileForRename(file *models.File) (*models.File, *models.File, error) {
|
||||||
@@ -169,6 +164,7 @@ func (self *WorkingTreeCommands) DiscardAllFileChanges(file *models.File) error
|
|||||||
if file.Added {
|
if file.Added {
|
||||||
return self.os.RemoveFile(file.Name)
|
return self.os.RemoveFile(file.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.DiscardUnstagedFileChanges(file)
|
return self.DiscardUnstagedFileChanges(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +172,8 @@ type IFileNode interface {
|
|||||||
ForEachFile(cb func(*models.File) error) error
|
ForEachFile(cb func(*models.File) error) error
|
||||||
GetFilePathsMatching(test func(*models.File) bool) []string
|
GetFilePathsMatching(test func(*models.File) bool) []string
|
||||||
GetPath() string
|
GetPath() string
|
||||||
|
// Returns file if the node is not a directory, otherwise returns nil
|
||||||
|
GetFile() *models.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) DiscardAllDirChanges(node IFileNode) error {
|
func (self *WorkingTreeCommands) DiscardAllDirChanges(node IFileNode) error {
|
||||||
@@ -184,13 +182,24 @@ func (self *WorkingTreeCommands) DiscardAllDirChanges(node IFileNode) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) DiscardUnstagedDirChanges(node IFileNode) error {
|
func (self *WorkingTreeCommands) DiscardUnstagedDirChanges(node IFileNode) error {
|
||||||
if err := self.RemoveUntrackedDirFiles(node); err != nil {
|
file := node.GetFile()
|
||||||
return err
|
if file == nil {
|
||||||
}
|
if err := self.RemoveUntrackedDirFiles(node); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("checkout").Arg("--", node.GetPath()).ToArgv()
|
cmdArgs := NewGitCmd("checkout").Arg("--", node.GetPath()).ToArgv()
|
||||||
if err := self.cmd.New(cmdArgs).Run(); err != nil {
|
if err := self.cmd.New(cmdArgs).Run(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if file.Added && !file.HasStagedChanges {
|
||||||
|
return self.os.RemoveFile(file.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := self.DiscardUnstagedFileChanges(file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -211,7 +220,6 @@ func (self *WorkingTreeCommands) RemoveUntrackedDirFiles(node IFileNode) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscardUnstagedFileChanges directly
|
|
||||||
func (self *WorkingTreeCommands) DiscardUnstagedFileChanges(file *models.File) error {
|
func (self *WorkingTreeCommands) DiscardUnstagedFileChanges(file *models.File) error {
|
||||||
cmdArgs := NewGitCmd("checkout").Arg("--", file.Name).ToArgv()
|
cmdArgs := NewGitCmd("checkout").Arg("--", file.Name).ToArgv()
|
||||||
return self.cmd.New(cmdArgs).Run()
|
return self.cmd.New(cmdArgs).Run()
|
||||||
@@ -228,34 +236,38 @@ func (self *WorkingTreeCommands) Exclude(filename string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WorktreeFileDiff returns the diff of a file
|
// WorktreeFileDiff returns the diff of a file
|
||||||
func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool, cached bool, ignoreWhitespace bool) string {
|
func (self *WorkingTreeCommands) WorktreeFileDiff(file *models.File, plain bool, cached bool) string {
|
||||||
// for now we assume an error means the file was deleted
|
// for now we assume an error means the file was deleted
|
||||||
s, _ := self.WorktreeFileDiffCmdObj(file, plain, cached, ignoreWhitespace).RunWithOutput()
|
s, _ := self.WorktreeFileDiffCmdObj(file, plain, cached).RunWithOutput()
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool, ignoreWhitespace bool) oscommands.ICmdObj {
|
func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain bool, cached bool) oscommands.ICmdObj {
|
||||||
colorArg := self.UserConfig.Git.Paging.ColorArg
|
colorArg := self.UserConfig.Git.Paging.ColorArg
|
||||||
if plain {
|
if plain {
|
||||||
colorArg = "never"
|
colorArg = "never"
|
||||||
}
|
}
|
||||||
|
|
||||||
contextSize := self.UserConfig.Git.DiffContextSize
|
contextSize := self.AppState.DiffContextSize
|
||||||
prevPath := node.GetPreviousPath()
|
prevPath := node.GetPreviousPath()
|
||||||
noIndex := !node.GetIsTracked() && !node.GetHasStagedChanges() && !cached && node.GetIsFile()
|
noIndex := !node.GetIsTracked() && !node.GetHasStagedChanges() && !cached && node.GetIsFile()
|
||||||
|
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||||
|
useExtDiff := extDiffCmd != "" && !plain
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("diff").
|
cmdArgs := NewGitCmd("diff").
|
||||||
|
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||||
|
ArgIfElse(useExtDiff, "--ext-diff", "--no-ext-diff").
|
||||||
Arg("--submodule").
|
Arg("--submodule").
|
||||||
Arg("--no-ext-diff").
|
|
||||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||||
Arg(fmt.Sprintf("--color=%s", colorArg)).
|
Arg(fmt.Sprintf("--color=%s", colorArg)).
|
||||||
ArgIf(ignoreWhitespace, "--ignore-all-space").
|
ArgIf(!plain && self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||||
ArgIf(cached, "--cached").
|
ArgIf(cached, "--cached").
|
||||||
ArgIf(noIndex, "--no-index").
|
ArgIf(noIndex, "--no-index").
|
||||||
Arg("--").
|
Arg("--").
|
||||||
ArgIf(noIndex, "/dev/null").
|
ArgIf(noIndex, "/dev/null").
|
||||||
Arg(node.GetPath()).
|
Arg(node.GetPath()).
|
||||||
ArgIf(prevPath != "", prevPath).
|
ArgIf(prevPath != "", prevPath).
|
||||||
|
Dir(self.repoPaths.worktreePath).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
@@ -263,34 +275,35 @@ func (self *WorkingTreeCommands) WorktreeFileDiffCmdObj(node models.IFile, plain
|
|||||||
|
|
||||||
// ShowFileDiff get the diff of specified from and to. Typically this will be used for a single commit so it'll be 123abc^..123abc
|
// ShowFileDiff get the diff of specified from and to. Typically this will be used for a single commit so it'll be 123abc^..123abc
|
||||||
// but when we're in diff mode it could be any 'from' to any 'to'. The reverse flag is also here thanks to diff mode.
|
// but when we're in diff mode it could be any 'from' to any 'to'. The reverse flag is also here thanks to diff mode.
|
||||||
func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bool, fileName string, plain bool,
|
func (self *WorkingTreeCommands) ShowFileDiff(from string, to string, reverse bool, fileName string, plain bool) (string, error) {
|
||||||
ignoreWhitespace bool,
|
return self.ShowFileDiffCmdObj(from, to, reverse, fileName, plain).RunWithOutput()
|
||||||
) (string, error) {
|
|
||||||
return self.ShowFileDiffCmdObj(from, to, reverse, fileName, plain, ignoreWhitespace).RunWithOutput()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool,
|
func (self *WorkingTreeCommands) ShowFileDiffCmdObj(from string, to string, reverse bool, fileName string, plain bool) oscommands.ICmdObj {
|
||||||
ignoreWhitespace bool,
|
contextSize := self.AppState.DiffContextSize
|
||||||
) oscommands.ICmdObj {
|
|
||||||
contextSize := self.UserConfig.Git.DiffContextSize
|
|
||||||
|
|
||||||
colorArg := self.UserConfig.Git.Paging.ColorArg
|
colorArg := self.UserConfig.Git.Paging.ColorArg
|
||||||
if plain {
|
if plain {
|
||||||
colorArg = "never"
|
colorArg = "never"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extDiffCmd := self.UserConfig.Git.Paging.ExternalDiffCommand
|
||||||
|
useExtDiff := extDiffCmd != "" && !plain
|
||||||
|
|
||||||
cmdArgs := NewGitCmd("diff").
|
cmdArgs := NewGitCmd("diff").
|
||||||
|
ConfigIf(useExtDiff, "diff.external="+extDiffCmd).
|
||||||
|
ArgIfElse(useExtDiff, "--ext-diff", "--no-ext-diff").
|
||||||
Arg("--submodule").
|
Arg("--submodule").
|
||||||
Arg("--no-ext-diff").
|
|
||||||
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
Arg(fmt.Sprintf("--unified=%d", contextSize)).
|
||||||
Arg("--no-renames").
|
Arg("--no-renames").
|
||||||
Arg(fmt.Sprintf("--color=%s", colorArg)).
|
Arg(fmt.Sprintf("--color=%s", colorArg)).
|
||||||
Arg(from).
|
Arg(from).
|
||||||
Arg(to).
|
Arg(to).
|
||||||
ArgIf(reverse, "-R").
|
ArgIf(reverse, "-R").
|
||||||
ArgIf(ignoreWhitespace, "--ignore-all-space").
|
ArgIf(!plain && self.AppState.IgnoreWhitespaceInDiffView, "--ignore-all-space").
|
||||||
Arg("--").
|
Arg("--").
|
||||||
Arg(fileName).
|
Arg(fileName).
|
||||||
|
Dir(self.repoPaths.worktreePath).
|
||||||
ToArgv()
|
ToArgv()
|
||||||
|
|
||||||
return self.cmd.New(cmdArgs).DontLog()
|
return self.cmd.New(cmdArgs).DontLog()
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "cached",
|
testName: "cached",
|
||||||
@@ -245,7 +245,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--color=always", "--cached", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--cached", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "plain",
|
testName: "plain",
|
||||||
@@ -259,7 +259,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--color=never", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=never", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "File not tracked and file has no staged changes",
|
testName: "File not tracked and file has no staged changes",
|
||||||
@@ -273,7 +273,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--no-index", "--", "/dev/null", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Default case (ignore whitespace)",
|
testName: "Default case (ignore whitespace)",
|
||||||
@@ -287,7 +287,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: true,
|
ignoreWhitespace: true,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--color=always", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--color=always", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Show diff with custom context size",
|
testName: "Show diff with custom context size",
|
||||||
@@ -301,7 +301,7 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 17,
|
contextSize: 17,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=17", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=17", "--color=always", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,10 +309,15 @@ func TestWorkingTreeDiff(t *testing.T) {
|
|||||||
s := s
|
s := s
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
userConfig := config.GetDefaultConfig()
|
userConfig := config.GetDefaultConfig()
|
||||||
userConfig.Git.DiffContextSize = s.contextSize
|
appState := &config.AppState{}
|
||||||
|
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
|
||||||
|
appState.DiffContextSize = s.contextSize
|
||||||
|
repoPaths := RepoPaths{
|
||||||
|
worktreePath: "/path/to/worktree",
|
||||||
|
}
|
||||||
|
|
||||||
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig})
|
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig, appState: appState, repoPaths: &repoPaths})
|
||||||
result := instance.WorktreeFileDiff(s.file, s.plain, s.cached, s.ignoreWhitespace)
|
result := instance.WorktreeFileDiff(s.file, s.plain, s.cached)
|
||||||
assert.Equal(t, expectedResult, result)
|
assert.Equal(t, expectedResult, result)
|
||||||
s.runner.CheckForMissingCalls()
|
s.runner.CheckForMissingCalls()
|
||||||
})
|
})
|
||||||
@@ -343,7 +348,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Show diff with custom context size",
|
testName: "Show diff with custom context size",
|
||||||
@@ -354,7 +359,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: false,
|
ignoreWhitespace: false,
|
||||||
contextSize: 123,
|
contextSize: 123,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=123", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=123", "--no-renames", "--color=always", "1234567890", "0987654321", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: "Default case (ignore whitespace)",
|
testName: "Default case (ignore whitespace)",
|
||||||
@@ -365,7 +370,7 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||||||
ignoreWhitespace: true,
|
ignoreWhitespace: true,
|
||||||
contextSize: 3,
|
contextSize: 3,
|
||||||
runner: oscommands.NewFakeRunner(t).
|
runner: oscommands.NewFakeRunner(t).
|
||||||
ExpectGitArgs([]string{"diff", "--submodule", "--no-ext-diff", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
|
ExpectGitArgs([]string{"-C", "/path/to/worktree", "diff", "--no-ext-diff", "--submodule", "--unified=3", "--no-renames", "--color=always", "1234567890", "0987654321", "--ignore-all-space", "--", "test.txt"}, expectedResult, nil),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,11 +378,16 @@ func TestWorkingTreeShowFileDiff(t *testing.T) {
|
|||||||
s := s
|
s := s
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
userConfig := config.GetDefaultConfig()
|
userConfig := config.GetDefaultConfig()
|
||||||
userConfig.Git.DiffContextSize = s.contextSize
|
appState := &config.AppState{}
|
||||||
|
appState.IgnoreWhitespaceInDiffView = s.ignoreWhitespace
|
||||||
|
appState.DiffContextSize = s.contextSize
|
||||||
|
repoPaths := RepoPaths{
|
||||||
|
worktreePath: "/path/to/worktree",
|
||||||
|
}
|
||||||
|
|
||||||
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig})
|
instance := buildWorkingTreeCommands(commonDeps{runner: s.runner, userConfig: userConfig, appState: appState, repoPaths: &repoPaths})
|
||||||
|
|
||||||
result, err := instance.ShowFileDiff(s.from, s.to, s.reverse, "test.txt", s.plain, s.ignoreWhitespace)
|
result, err := instance.ShowFileDiff(s.from, s.to, s.reverse, "test.txt", s.plain)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expectedResult, result)
|
assert.Equal(t, expectedResult, result)
|
||||||
s.runner.CheckForMissingCalls()
|
s.runner.CheckForMissingCalls()
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package git_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WorktreeCommands struct {
|
||||||
|
*GitCommon
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWorktreeCommands(gitCommon *GitCommon) *WorktreeCommands {
|
||||||
|
return &WorktreeCommands{
|
||||||
|
GitCommon: gitCommon,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewWorktreeOpts struct {
|
||||||
|
// required. The path of the new worktree.
|
||||||
|
Path string
|
||||||
|
// required. The base branch/ref.
|
||||||
|
Base string
|
||||||
|
|
||||||
|
// if true, ends up with a detached head
|
||||||
|
Detach bool
|
||||||
|
|
||||||
|
// optional. if empty, and if detach is false, we will checkout the base
|
||||||
|
Branch string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeCommands) New(opts NewWorktreeOpts) error {
|
||||||
|
if opts.Detach && opts.Branch != "" {
|
||||||
|
panic("cannot specify branch when detaching")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdArgs := NewGitCmd("worktree").Arg("add").
|
||||||
|
ArgIf(opts.Detach, "--detach").
|
||||||
|
ArgIf(opts.Branch != "", "-b", opts.Branch).
|
||||||
|
Arg(opts.Path, opts.Base)
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs.ToArgv()).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeCommands) Delete(worktreePath string, force bool) error {
|
||||||
|
cmdArgs := NewGitCmd("worktree").Arg("remove").ArgIf(force, "-f").Arg(worktreePath).ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeCommands) Detach(worktreePath string) error {
|
||||||
|
cmdArgs := NewGitCmd("checkout").Arg("--detach").GitDir(filepath.Join(worktreePath, ".git")).ToArgv()
|
||||||
|
|
||||||
|
return self.cmd.New(cmdArgs).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func WorktreeForBranch(branch *models.Branch, worktrees []*models.Worktree) (*models.Worktree, bool) {
|
||||||
|
for _, worktree := range worktrees {
|
||||||
|
if worktree.Branch == branch.Name {
|
||||||
|
return worktree, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckedOutByOtherWorktree(branch *models.Branch, worktrees []*models.Worktree) bool {
|
||||||
|
worktree, ok := WorktreeForBranch(branch, worktrees)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !worktree.IsCurrent
|
||||||
|
}
|
||||||
@@ -0,0 +1,275 @@
|
|||||||
|
package git_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
iofs "io/fs"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WorktreeLoader struct {
|
||||||
|
*GitCommon
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWorktreeLoader(gitCommon *GitCommon) *WorktreeLoader {
|
||||||
|
return &WorktreeLoader{GitCommon: gitCommon}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeLoader) GetWorktrees() ([]*models.Worktree, error) {
|
||||||
|
currentRepoPath := self.repoPaths.RepoPath()
|
||||||
|
worktreePath := self.repoPaths.WorktreePath()
|
||||||
|
|
||||||
|
cmdArgs := NewGitCmd("worktree").Arg("list", "--porcelain").ToArgv()
|
||||||
|
worktreesOutput, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
splitLines := strings.Split(
|
||||||
|
utils.NormalizeLinefeeds(worktreesOutput), "\n",
|
||||||
|
)
|
||||||
|
|
||||||
|
var worktrees []*models.Worktree
|
||||||
|
var current *models.Worktree
|
||||||
|
for _, splitLine := range splitLines {
|
||||||
|
// worktrees are defined over multiple lines and are separated by blank lines
|
||||||
|
// so if we reach a blank line we're done with the current worktree
|
||||||
|
if len(splitLine) == 0 && current != nil {
|
||||||
|
worktrees = append(worktrees, current)
|
||||||
|
current = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore bare repo (not sure why it's even appearing in this list: it's not a worktree)
|
||||||
|
if splitLine == "bare" {
|
||||||
|
current = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(splitLine, "worktree ") {
|
||||||
|
path := strings.SplitN(splitLine, " ", 2)[1]
|
||||||
|
isMain := path == currentRepoPath
|
||||||
|
isCurrent := path == worktreePath
|
||||||
|
isPathMissing := self.pathExists(path)
|
||||||
|
|
||||||
|
current = &models.Worktree{
|
||||||
|
IsMain: isMain,
|
||||||
|
IsCurrent: isCurrent,
|
||||||
|
IsPathMissing: isPathMissing,
|
||||||
|
Path: path,
|
||||||
|
// we defer populating GitDir until a loop below so that
|
||||||
|
// we can parallelize the calls to git rev-parse
|
||||||
|
GitDir: "",
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(splitLine, "branch ") {
|
||||||
|
branch := strings.SplitN(splitLine, " ", 2)[1]
|
||||||
|
current.Branch = strings.TrimPrefix(branch, "refs/heads/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
wg.Add(len(worktrees))
|
||||||
|
for _, worktree := range worktrees {
|
||||||
|
worktree := worktree
|
||||||
|
|
||||||
|
go utils.Safe(func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
if worktree.IsPathMissing {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gitDir, err := callGitRevParseWithDir(self.cmd, self.version, worktree.Path, "--absolute-git-dir")
|
||||||
|
if err != nil {
|
||||||
|
self.Log.Warnf("Could not find git dir for worktree %s: %v", worktree.Path, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
worktree.GitDir = gitDir
|
||||||
|
})
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
names := getUniqueNamesFromPaths(lo.Map(worktrees, func(worktree *models.Worktree, _ int) string {
|
||||||
|
return worktree.Path
|
||||||
|
}))
|
||||||
|
|
||||||
|
for index, worktree := range worktrees {
|
||||||
|
worktree.Name = names[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
// move current worktree to the top
|
||||||
|
for i, worktree := range worktrees {
|
||||||
|
if worktree.IsCurrent {
|
||||||
|
worktrees = append(worktrees[:i], worktrees[i+1:]...)
|
||||||
|
worktrees = append([]*models.Worktree{worktree}, worktrees...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some worktrees are on a branch but are mid-rebase, and in those cases,
|
||||||
|
// `git worktree list` will not show the branch name. We can get the branch
|
||||||
|
// name from the `rebase-merge/head-name` file (if it exists) in the folder
|
||||||
|
// for the worktree in the parent repo's .git/worktrees folder.
|
||||||
|
for _, worktree := range worktrees {
|
||||||
|
// No point checking if we already have a branch name
|
||||||
|
if worktree.Branch != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we couldn't find the git directory, we can't find the branch name
|
||||||
|
if worktree.GitDir == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rebasedBranch, ok := self.rebasedBranch(worktree)
|
||||||
|
if ok {
|
||||||
|
worktree.Branch = rebasedBranch
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bisectedBranch, ok := self.bisectedBranch(worktree)
|
||||||
|
if ok {
|
||||||
|
worktree.Branch = bisectedBranch
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return worktrees, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeLoader) pathExists(path string) bool {
|
||||||
|
if _, err := self.Fs.Stat(path); err != nil {
|
||||||
|
if errors.Is(err, iofs.ErrNotExist) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
self.Log.Errorf("failed to check if worktree path `%s` exists\n%v", path, err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeLoader) rebasedBranch(worktree *models.Worktree) (string, bool) {
|
||||||
|
for _, dir := range []string{"rebase-merge", "rebase-apply"} {
|
||||||
|
if bytesContent, err := afero.ReadFile(self.Fs, filepath.Join(worktree.GitDir, dir, "head-name")); err == nil {
|
||||||
|
headName := strings.TrimSpace(string(bytesContent))
|
||||||
|
shortHeadName := strings.TrimPrefix(headName, "refs/heads/")
|
||||||
|
return shortHeadName, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WorktreeLoader) bisectedBranch(worktree *models.Worktree) (string, bool) {
|
||||||
|
bisectStartPath := filepath.Join(worktree.GitDir, "BISECT_START")
|
||||||
|
startContent, err := afero.ReadFile(self.Fs, bisectStartPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(string(startContent)), true
|
||||||
|
}
|
||||||
|
|
||||||
|
type pathWithIndexT struct {
|
||||||
|
path string
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
type nameWithIndexT struct {
|
||||||
|
name string
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUniqueNamesFromPaths(paths []string) []string {
|
||||||
|
pathsWithIndex := lo.Map(paths, func(path string, index int) pathWithIndexT {
|
||||||
|
return pathWithIndexT{path, index}
|
||||||
|
})
|
||||||
|
|
||||||
|
namesWithIndex := getUniqueNamesFromPathsAux(pathsWithIndex, 0)
|
||||||
|
|
||||||
|
// now sort based on index
|
||||||
|
result := make([]string, len(namesWithIndex))
|
||||||
|
for _, nameWithIndex := range namesWithIndex {
|
||||||
|
result[nameWithIndex.index] = nameWithIndex.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUniqueNamesFromPathsAux(paths []pathWithIndexT, depth int) []nameWithIndexT {
|
||||||
|
// If we have no paths, return an empty array
|
||||||
|
if len(paths) == 0 {
|
||||||
|
return []nameWithIndexT{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have only one path, return the last segment of the path
|
||||||
|
if len(paths) == 1 {
|
||||||
|
path := paths[0]
|
||||||
|
return []nameWithIndexT{{index: path.index, name: sliceAtDepth(path.path, depth)}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// group the paths by their value at the specified depth
|
||||||
|
groups := make(map[string][]pathWithIndexT)
|
||||||
|
for _, path := range paths {
|
||||||
|
value := valueAtDepth(path.path, depth)
|
||||||
|
groups[value] = append(groups[value], path)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []nameWithIndexT{}
|
||||||
|
for _, group := range groups {
|
||||||
|
if len(group) == 1 {
|
||||||
|
path := group[0]
|
||||||
|
result = append(result, nameWithIndexT{index: path.index, name: sliceAtDepth(path.path, depth)})
|
||||||
|
} else {
|
||||||
|
result = append(result, getUniqueNamesFromPathsAux(group, depth+1)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the path is /a/b/c/d, and the depth is 0, the value is 'd'. If the depth is 1, the value is 'c', etc
|
||||||
|
func valueAtDepth(path string, depth int) string {
|
||||||
|
path = strings.TrimPrefix(path, "/")
|
||||||
|
path = strings.TrimSuffix(path, "/")
|
||||||
|
|
||||||
|
// Split the path into segments
|
||||||
|
segments := strings.Split(path, "/")
|
||||||
|
|
||||||
|
// Get the length of segments
|
||||||
|
length := len(segments)
|
||||||
|
|
||||||
|
// If the depth is greater than the length of segments, return an empty string
|
||||||
|
if depth >= length {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the segment at the specified depth from the end of the path
|
||||||
|
return segments[length-1-depth]
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the path is /a/b/c/d, and the depth is 0, the value is 'd'. If the depth is 1, the value is 'b/c', etc
|
||||||
|
func sliceAtDepth(path string, depth int) string {
|
||||||
|
path = strings.TrimPrefix(path, "/")
|
||||||
|
path = strings.TrimSuffix(path, "/")
|
||||||
|
|
||||||
|
// Split the path into segments
|
||||||
|
segments := strings.Split(path, "/")
|
||||||
|
|
||||||
|
// Get the length of segments
|
||||||
|
length := len(segments)
|
||||||
|
|
||||||
|
// If the depth is greater than or equal to the length of segments, return an empty string
|
||||||
|
if depth >= length {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join the segments from the specified depth till end of the path
|
||||||
|
return strings.Join(segments[length-1-depth:], "/")
|
||||||
|
}
|
||||||
@@ -0,0 +1,261 @@
|
|||||||
|
package git_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetWorktrees(t *testing.T) {
|
||||||
|
type scenario struct {
|
||||||
|
testName string
|
||||||
|
repoPaths *RepoPaths
|
||||||
|
before func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn)
|
||||||
|
expectedWorktrees []*models.Worktree
|
||||||
|
expectedErr string
|
||||||
|
}
|
||||||
|
|
||||||
|
scenarios := []scenario{
|
||||||
|
{
|
||||||
|
testName: "Single worktree (main)",
|
||||||
|
repoPaths: &RepoPaths{
|
||||||
|
repoPath: "/path/to/repo",
|
||||||
|
worktreePath: "/path/to/repo",
|
||||||
|
},
|
||||||
|
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
|
||||||
|
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
|
||||||
|
`worktree /path/to/repo
|
||||||
|
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
|
||||||
|
branch refs/heads/mybranch
|
||||||
|
`,
|
||||||
|
nil)
|
||||||
|
|
||||||
|
gitArgsMainWorktree := append(append([]string{"-C", "/path/to/repo"}, getRevParseArgs()...), "--absolute-git-dir")
|
||||||
|
runner.ExpectGitArgs(gitArgsMainWorktree, "/path/to/repo/.git", nil)
|
||||||
|
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
|
||||||
|
},
|
||||||
|
expectedWorktrees: []*models.Worktree{
|
||||||
|
{
|
||||||
|
IsMain: true,
|
||||||
|
IsCurrent: true,
|
||||||
|
Path: "/path/to/repo",
|
||||||
|
IsPathMissing: false,
|
||||||
|
GitDir: "/path/to/repo/.git",
|
||||||
|
Branch: "mybranch",
|
||||||
|
Name: "repo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "Multiple worktrees (main + linked)",
|
||||||
|
repoPaths: &RepoPaths{
|
||||||
|
repoPath: "/path/to/repo",
|
||||||
|
worktreePath: "/path/to/repo",
|
||||||
|
},
|
||||||
|
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
|
||||||
|
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
|
||||||
|
`worktree /path/to/repo
|
||||||
|
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
|
||||||
|
branch refs/heads/mybranch
|
||||||
|
|
||||||
|
worktree /path/to/repo-worktree
|
||||||
|
HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
|
||||||
|
branch refs/heads/mybranch-worktree
|
||||||
|
`,
|
||||||
|
nil)
|
||||||
|
gitArgsMainWorktree := append(append([]string{"-C", "/path/to/repo"}, getRevParseArgs()...), "--absolute-git-dir")
|
||||||
|
runner.ExpectGitArgs(gitArgsMainWorktree, "/path/to/repo/.git", nil)
|
||||||
|
gitArgsLinkedWorktree := append(append([]string{"-C", "/path/to/repo-worktree"}, getRevParseArgs()...), "--absolute-git-dir")
|
||||||
|
runner.ExpectGitArgs(gitArgsLinkedWorktree, "/path/to/repo/.git/worktrees/repo-worktree", nil)
|
||||||
|
|
||||||
|
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
|
||||||
|
_ = fs.MkdirAll("/path/to/repo-worktree", 0o755)
|
||||||
|
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/repo-worktree", 0o755)
|
||||||
|
_ = afero.WriteFile(fs, "/path/to/repo-worktree/.git", []byte("gitdir: /path/to/repo/.git/worktrees/repo-worktree"), 0o755)
|
||||||
|
},
|
||||||
|
expectedWorktrees: []*models.Worktree{
|
||||||
|
{
|
||||||
|
IsMain: true,
|
||||||
|
IsCurrent: true,
|
||||||
|
Path: "/path/to/repo",
|
||||||
|
IsPathMissing: false,
|
||||||
|
GitDir: "/path/to/repo/.git",
|
||||||
|
Branch: "mybranch",
|
||||||
|
Name: "repo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IsMain: false,
|
||||||
|
IsCurrent: false,
|
||||||
|
Path: "/path/to/repo-worktree",
|
||||||
|
IsPathMissing: false,
|
||||||
|
GitDir: "/path/to/repo/.git/worktrees/repo-worktree",
|
||||||
|
Branch: "mybranch-worktree",
|
||||||
|
Name: "repo-worktree",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "Worktree missing path",
|
||||||
|
repoPaths: &RepoPaths{
|
||||||
|
repoPath: "/path/to/repo",
|
||||||
|
worktreePath: "/path/to/repo",
|
||||||
|
},
|
||||||
|
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
|
||||||
|
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
|
||||||
|
`worktree /path/to/worktree
|
||||||
|
HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
|
||||||
|
branch refs/heads/missingbranch
|
||||||
|
`,
|
||||||
|
nil)
|
||||||
|
|
||||||
|
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
|
||||||
|
},
|
||||||
|
expectedWorktrees: []*models.Worktree{
|
||||||
|
{
|
||||||
|
IsMain: false,
|
||||||
|
IsCurrent: false,
|
||||||
|
Path: "/path/to/worktree",
|
||||||
|
IsPathMissing: true,
|
||||||
|
GitDir: "",
|
||||||
|
Branch: "missingbranch",
|
||||||
|
Name: "worktree",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "In linked worktree",
|
||||||
|
repoPaths: &RepoPaths{
|
||||||
|
repoPath: "/path/to/repo",
|
||||||
|
worktreePath: "/path/to/repo-worktree",
|
||||||
|
},
|
||||||
|
before: func(runner *oscommands.FakeCmdObjRunner, fs afero.Fs, getRevParseArgs argFn) {
|
||||||
|
runner.ExpectGitArgs([]string{"worktree", "list", "--porcelain"},
|
||||||
|
`worktree /path/to/repo
|
||||||
|
HEAD d85cc9d281fa6ae1665c68365fc70e75e82a042d
|
||||||
|
branch refs/heads/mybranch
|
||||||
|
|
||||||
|
worktree /path/to/repo-worktree
|
||||||
|
HEAD 775955775e79b8f5b4c4b56f82fbf657e2d5e4de
|
||||||
|
branch refs/heads/mybranch-worktree
|
||||||
|
`,
|
||||||
|
nil)
|
||||||
|
gitArgsMainWorktree := append(append([]string{"-C", "/path/to/repo"}, getRevParseArgs()...), "--absolute-git-dir")
|
||||||
|
runner.ExpectGitArgs(gitArgsMainWorktree, "/path/to/repo/.git", nil)
|
||||||
|
gitArgsLinkedWorktree := append(append([]string{"-C", "/path/to/repo-worktree"}, getRevParseArgs()...), "--absolute-git-dir")
|
||||||
|
runner.ExpectGitArgs(gitArgsLinkedWorktree, "/path/to/repo/.git/worktrees/repo-worktree", nil)
|
||||||
|
|
||||||
|
_ = fs.MkdirAll("/path/to/repo/.git", 0o755)
|
||||||
|
_ = fs.MkdirAll("/path/to/repo-worktree", 0o755)
|
||||||
|
_ = fs.MkdirAll("/path/to/repo/.git/worktrees/repo-worktree", 0o755)
|
||||||
|
_ = afero.WriteFile(fs, "/path/to/repo-worktree/.git", []byte("gitdir: /path/to/repo/.git/worktrees/repo-worktree"), 0o755)
|
||||||
|
},
|
||||||
|
expectedWorktrees: []*models.Worktree{
|
||||||
|
{
|
||||||
|
IsMain: false,
|
||||||
|
IsCurrent: true,
|
||||||
|
Path: "/path/to/repo-worktree",
|
||||||
|
IsPathMissing: false,
|
||||||
|
GitDir: "/path/to/repo/.git/worktrees/repo-worktree",
|
||||||
|
Branch: "mybranch-worktree",
|
||||||
|
Name: "repo-worktree",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IsMain: true,
|
||||||
|
IsCurrent: false,
|
||||||
|
Path: "/path/to/repo",
|
||||||
|
IsPathMissing: false,
|
||||||
|
GitDir: "/path/to/repo/.git",
|
||||||
|
Branch: "mybranch",
|
||||||
|
Name: "repo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
s := s
|
||||||
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
|
runner := oscommands.NewFakeRunner(t)
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
version, err := GetGitVersion(oscommands.NewDummyOSCommand())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
getRevParseArgs := func() []string {
|
||||||
|
args := []string{"rev-parse"}
|
||||||
|
if version.IsAtLeast(2, 31, 0) {
|
||||||
|
args = append(args, "--path-format=absolute")
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
s.before(runner, fs, getRevParseArgs)
|
||||||
|
|
||||||
|
loader := &WorktreeLoader{
|
||||||
|
GitCommon: buildGitCommon(commonDeps{runner: runner, fs: fs, repoPaths: s.repoPaths, gitVersion: version}),
|
||||||
|
}
|
||||||
|
|
||||||
|
worktrees, err := loader.GetWorktrees()
|
||||||
|
if s.expectedErr != "" {
|
||||||
|
assert.EqualError(t, errors.New(s.expectedErr), err.Error())
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, s.expectedWorktrees, worktrees)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUniqueNamesFromPaths(t *testing.T) {
|
||||||
|
for _, scenario := range []struct {
|
||||||
|
input []string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: []string{},
|
||||||
|
expected: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []string{
|
||||||
|
"/my/path/feature/one",
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"one",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []string{
|
||||||
|
"/my/path/feature/one/",
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"one",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []string{
|
||||||
|
"/a/b/c/d",
|
||||||
|
"/a/b/c/e",
|
||||||
|
"/a/b/f/d",
|
||||||
|
"/a/e/c/d",
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"b/c/d",
|
||||||
|
"e",
|
||||||
|
"f/d",
|
||||||
|
"e/c/d",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
actual := getUniqueNamesFromPaths(scenario.input)
|
||||||
|
assert.EqualValues(t, scenario.expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/secureexec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// including license from https://github.com/tcnksm/go-gitconfig because this file is an adaptation of that repo's code
|
// including license from https://github.com/tcnksm/go-gitconfig because this file is an adaptation of that repo's code
|
||||||
@@ -55,10 +53,10 @@ func runGitConfigCmd(cmd *exec.Cmd) (string, error) {
|
|||||||
|
|
||||||
func getGitConfigCmd(key string) *exec.Cmd {
|
func getGitConfigCmd(key string) *exec.Cmd {
|
||||||
gitArgs := []string{"config", "--get", "--null", key}
|
gitArgs := []string{"config", "--get", "--null", key}
|
||||||
return secureexec.Command("git", gitArgs...)
|
return exec.Command("git", gitArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitConfigGeneralCmd(args string) *exec.Cmd {
|
func getGitConfigGeneralCmd(args string) *exec.Cmd {
|
||||||
gitArgs := append([]string{"config"}, strings.Split(args, " ")...)
|
gitArgs := append([]string{"config"}, strings.Split(args, " ")...)
|
||||||
return secureexec.Command("git", gitArgs...)
|
return exec.Command("git", gitArgs...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,305 +0,0 @@
|
|||||||
package commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
|
||||||
gogit "github.com/jesseduffield/go-git/v5"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/git_config"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
||||||
"github.com/sasha-s/go-deadlock"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type fileInfoMock struct {
|
|
||||||
name string
|
|
||||||
size int64
|
|
||||||
fileMode os.FileMode
|
|
||||||
fileModTime time.Time
|
|
||||||
isDir bool
|
|
||||||
sys interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name is a function.
|
|
||||||
func (f fileInfoMock) Name() string {
|
|
||||||
return f.name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Size is a function.
|
|
||||||
func (f fileInfoMock) Size() int64 {
|
|
||||||
return f.size
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode is a function.
|
|
||||||
func (f fileInfoMock) Mode() os.FileMode {
|
|
||||||
return f.fileMode
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModTime is a function.
|
|
||||||
func (f fileInfoMock) ModTime() time.Time {
|
|
||||||
return f.fileModTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsDir is a function.
|
|
||||||
func (f fileInfoMock) IsDir() bool {
|
|
||||||
return f.isDir
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sys is a function.
|
|
||||||
func (f fileInfoMock) Sys() interface{} {
|
|
||||||
return f.sys
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestNavigateToRepoRootDirectory is a function.
|
|
||||||
func TestNavigateToRepoRootDirectory(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
stat func(string) (os.FileInfo, error)
|
|
||||||
chdir func(string) error
|
|
||||||
test func(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
"Navigate to git repository",
|
|
||||||
func(string) (os.FileInfo, error) {
|
|
||||||
return fileInfoMock{isDir: true}, nil
|
|
||||||
},
|
|
||||||
func(string) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func(err error) {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"An error occurred when getting path information",
|
|
||||||
func(string) (os.FileInfo, error) {
|
|
||||||
return nil, fmt.Errorf("An error occurred")
|
|
||||||
},
|
|
||||||
func(string) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func(err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.EqualError(t, err, "An error occurred")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"An error occurred when trying to move one path backward",
|
|
||||||
func(string) (os.FileInfo, error) {
|
|
||||||
return nil, os.ErrNotExist
|
|
||||||
},
|
|
||||||
func(string) error {
|
|
||||||
return fmt.Errorf("An error occurred")
|
|
||||||
},
|
|
||||||
func(err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.EqualError(t, err, "An error occurred")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
s := s
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
s.test(navigateToRepoRootDirectory(s.stat, s.chdir))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestSetupRepository is a function.
|
|
||||||
func TestSetupRepository(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
openGitRepository func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error)
|
|
||||||
errorStr string
|
|
||||||
options gogit.PlainOpenOptions
|
|
||||||
test func(*gogit.Repository, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
"A gitconfig parsing error occurred",
|
|
||||||
func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error) {
|
|
||||||
return nil, fmt.Errorf(`unquoted '\' must be followed by new line`)
|
|
||||||
},
|
|
||||||
"error translated",
|
|
||||||
gogit.PlainOpenOptions{},
|
|
||||||
func(r *gogit.Repository, err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.EqualError(t, err, "error translated")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"A gogit error occurred",
|
|
||||||
func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error) {
|
|
||||||
return nil, fmt.Errorf("Error from inside gogit")
|
|
||||||
},
|
|
||||||
"",
|
|
||||||
gogit.PlainOpenOptions{},
|
|
||||||
func(r *gogit.Repository, err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.EqualError(t, err, "Error from inside gogit")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Setup done properly",
|
|
||||||
func(string, *gogit.PlainOpenOptions) (*gogit.Repository, error) {
|
|
||||||
assert.NoError(t, os.RemoveAll("/tmp/lazygit-test"))
|
|
||||||
r, err := gogit.PlainInit("/tmp/lazygit-test", false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
return r, nil
|
|
||||||
},
|
|
||||||
"",
|
|
||||||
gogit.PlainOpenOptions{},
|
|
||||||
func(r *gogit.Repository, err error) {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, r)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
s := s
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
s.test(setupRepository(s.openGitRepository, s.options, s.errorStr))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestNewGitCommand is a function.
|
|
||||||
func TestNewGitCommand(t *testing.T) {
|
|
||||||
actual, err := os.Getwd()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
assert.NoError(t, os.Chdir(actual))
|
|
||||||
}()
|
|
||||||
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
setup func()
|
|
||||||
test func(*GitCommand, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
"An error occurred, folder doesn't contains a git repository",
|
|
||||||
func() {
|
|
||||||
assert.NoError(t, os.Chdir("/tmp"))
|
|
||||||
},
|
|
||||||
func(gitCmd *GitCommand, err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Regexp(t, `Must open lazygit in a git repository`, err.Error())
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"New GitCommand object created",
|
|
||||||
func() {
|
|
||||||
assert.NoError(t, os.RemoveAll("/tmp/lazygit-test"))
|
|
||||||
_, err := gogit.PlainInit("/tmp/lazygit-test", false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NoError(t, os.Chdir("/tmp/lazygit-test"))
|
|
||||||
},
|
|
||||||
func(gitCmd *GitCommand, err error) {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
s := s
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
s.setup()
|
|
||||||
s.test(
|
|
||||||
NewGitCommand(utils.NewDummyCommon(),
|
|
||||||
&git_commands.GitVersion{},
|
|
||||||
oscommands.NewDummyOSCommand(),
|
|
||||||
git_config.NewFakeGitConfig(nil),
|
|
||||||
&deadlock.Mutex{},
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindDotGitDir(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
stat func(string) (os.FileInfo, error)
|
|
||||||
readFile func(filename string) ([]byte, error)
|
|
||||||
test func(string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
".git is a directory",
|
|
||||||
func(dotGit string) (os.FileInfo, error) {
|
|
||||||
assert.Equal(t, ".git", dotGit)
|
|
||||||
return os.Stat("testdata/a_dir")
|
|
||||||
},
|
|
||||||
func(dotGit string) ([]byte, error) {
|
|
||||||
assert.Fail(t, "readFile should not be called if .git is a directory")
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
func(gitDir string, err error) {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, ".git", gitDir)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
".git is a file",
|
|
||||||
func(dotGit string) (os.FileInfo, error) {
|
|
||||||
assert.Equal(t, ".git", dotGit)
|
|
||||||
return os.Stat("testdata/a_file")
|
|
||||||
},
|
|
||||||
func(dotGit string) ([]byte, error) {
|
|
||||||
assert.Equal(t, ".git", dotGit)
|
|
||||||
return []byte("gitdir: blah\n"), nil
|
|
||||||
},
|
|
||||||
func(gitDir string, err error) {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, "blah", gitDir)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"os.Stat returns an error",
|
|
||||||
func(dotGit string) (os.FileInfo, error) {
|
|
||||||
assert.Equal(t, ".git", dotGit)
|
|
||||||
return nil, errors.New("error")
|
|
||||||
},
|
|
||||||
func(dotGit string) ([]byte, error) {
|
|
||||||
assert.Fail(t, "readFile should not be called os.Stat returns an error")
|
|
||||||
return nil, nil
|
|
||||||
},
|
|
||||||
func(gitDir string, err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"readFile returns an error",
|
|
||||||
func(dotGit string) (os.FileInfo, error) {
|
|
||||||
assert.Equal(t, ".git", dotGit)
|
|
||||||
return os.Stat("testdata/a_file")
|
|
||||||
},
|
|
||||||
func(dotGit string) ([]byte, error) {
|
|
||||||
return nil, errors.New("error")
|
|
||||||
},
|
|
||||||
func(gitDir string, err error) {
|
|
||||||
assert.Error(t, err)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
s := s
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
s.test(findDotGitDir(s.stat, s.readFile))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,9 +8,10 @@ import (
|
|||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/jesseduffield/lazygit/pkg/i18n"
|
"github.com/jesseduffield/lazygit/pkg/i18n"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This package is for handling logic specific to a git hosting service like github, gitlab, bitbucket, gitea, etc.
|
// This package is for handling logic specific to a git hosting service like github, gitlab, bitbucket, gitea, etc.
|
||||||
@@ -98,33 +99,30 @@ func (self *HostingServiceMgr) getCandidateServiceDomains() []ServiceDomain {
|
|||||||
|
|
||||||
serviceDomains := slices.Clone(defaultServiceDomains)
|
serviceDomains := slices.Clone(defaultServiceDomains)
|
||||||
|
|
||||||
if len(self.configServiceDomains) > 0 {
|
for gitDomain, typeAndDomain := range self.configServiceDomains {
|
||||||
for gitDomain, typeAndDomain := range self.configServiceDomains {
|
provider, webDomain, success := strings.Cut(typeAndDomain, ":")
|
||||||
splitData := strings.Split(typeAndDomain, ":")
|
|
||||||
if len(splitData) != 2 {
|
|
||||||
self.log.Errorf("Unexpected format for git service: '%s'. Expected something like 'github.com:github.com'", typeAndDomain)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
provider := splitData[0]
|
// we allow for one ':' for specifying the TCP port
|
||||||
webDomain := splitData[1]
|
if !success || strings.Count(webDomain, ":") > 1 {
|
||||||
|
self.log.Errorf("Unexpected format for git service: '%s'. Expected something like 'github.com:github.com'", typeAndDomain)
|
||||||
serviceDefinition, ok := serviceDefinitionByProvider[provider]
|
continue
|
||||||
if !ok {
|
|
||||||
providerNames := slices.Map(serviceDefinitions, func(serviceDefinition ServiceDefinition) string {
|
|
||||||
return serviceDefinition.provider
|
|
||||||
})
|
|
||||||
|
|
||||||
self.log.Errorf("Unknown git service type: '%s'. Expected one of %s", provider, strings.Join(providerNames, ", "))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceDomains = append(serviceDomains, ServiceDomain{
|
|
||||||
gitDomain: gitDomain,
|
|
||||||
webDomain: webDomain,
|
|
||||||
serviceDefinition: serviceDefinition,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serviceDefinition, ok := serviceDefinitionByProvider[provider]
|
||||||
|
if !ok {
|
||||||
|
providerNames := lo.Map(serviceDefinitions, func(serviceDefinition ServiceDefinition, _ int) string {
|
||||||
|
return serviceDefinition.provider
|
||||||
|
})
|
||||||
|
|
||||||
|
self.log.Errorf("Unknown git service type: '%s'. Expected one of %s", provider, strings.Join(providerNames, ", "))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceDomains = append(serviceDomains, ServiceDomain{
|
||||||
|
gitDomain: gitDomain,
|
||||||
|
webDomain: webDomain,
|
||||||
|
serviceDefinition: serviceDefinition,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceDomains
|
return serviceDomains
|
||||||
|
|||||||
@@ -340,6 +340,30 @@ func TestGetPullRequestURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedLoggedErrors: nil,
|
expectedLoggedErrors: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
testName: "Does not log error when config service webDomain contains a port",
|
||||||
|
from: "feature/profile-page",
|
||||||
|
remoteUrl: "git@my.domain.test:johndoe/social_network.git",
|
||||||
|
configServiceDomains: map[string]string{
|
||||||
|
"my.domain.test": "gitlab:my.domain.test:1111",
|
||||||
|
},
|
||||||
|
test: func(url string, err error) {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "https://my.domain.test:1111/johndoe/social_network/-/merge_requests/new?merge_request[source_branch]=feature%2Fprofile-page", url)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testName: "Logs error when webDomain contains more than one colon",
|
||||||
|
from: "feature/profile-page",
|
||||||
|
remoteUrl: "git@my.domain.test:johndoe/social_network.git",
|
||||||
|
configServiceDomains: map[string]string{
|
||||||
|
"my.domain.test": "gitlab:my.domain.test:1111:2222",
|
||||||
|
},
|
||||||
|
test: func(url string, err error) {
|
||||||
|
assert.Error(t, err)
|
||||||
|
},
|
||||||
|
expectedLoggedErrors: []string{"Unexpected format for git service: 'gitlab:my.domain.test:1111:2222'. Expected something like 'github.com:github.com'"},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
testName: "Logs error when config service domain is malformed",
|
testName: "Logs error when config service domain is malformed",
|
||||||
from: "feature/profile-page",
|
from: "feature/profile-page",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user