gitnow.fish 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. # GitNow — Speed up your Git workflow. 🐠
  2. # https://github.com/joseluisq/gitnow
  3. function __gitnow_install -e gitnow_install
  4. echo (gitnow -v)" is installed and ready to use!"
  5. echo "Just run the `gitnow` command if you want explore the API."
  6. end
  7. function __gitnow_uninstall -e gitnow_uninstall
  8. echo "GitNow was uninstalled successfully."
  9. end
  10. function gitnow -d "Gitnow: Speed up your Git workflow. 🐠" -a xversion
  11. if [ "$xversion" = "-v" ]; or [ "$xversion" = "--version" ]
  12. echo "GitNow version $gitnow_version"
  13. else
  14. __gitnow_manual | command less -r
  15. commandline -f repaint
  16. end
  17. end
  18. function state -d "Gitnow: Show the working tree status in compact way"
  19. if not __gitnow_is_git_repository
  20. __gitnow_msg_not_valid_repository "state"
  21. return
  22. end
  23. command git status -sb
  24. commandline -f repaint
  25. end
  26. function stage -d "Gitnow: Stage files in current working directory"
  27. if not __gitnow_is_git_repository
  28. __gitnow_msg_not_valid_repository "stage"
  29. return
  30. end
  31. set -l len (count $argv)
  32. set -l opts .
  33. if test $len -gt 0
  34. set opts $argv
  35. end
  36. command git add $opts
  37. commandline -f repaint
  38. end
  39. function unstage -d "Gitnow: Unstage files in current working directory"
  40. if not __gitnow_is_git_repository
  41. __gitnow_msg_not_valid_repository "unstage"
  42. return
  43. end
  44. set -l len (count $argv)
  45. set -l opts .
  46. if test $len -gt 0
  47. set opts $argv
  48. end
  49. command git reset $opts
  50. commandline -f repaint
  51. end
  52. function show -d "Gitnow: Show commit detail objects"
  53. if not __gitnow_is_git_repository
  54. __gitnow_msg_not_valid_repository "show"
  55. return
  56. end
  57. set -l len (count $argv)
  58. if test $len -gt 0
  59. command git show $argv
  60. else
  61. command git show --compact-summary --patch HEAD
  62. end
  63. commandline -f repaint
  64. end
  65. function untracked -d "Gitnow: Check for untracked files and directories on current working directory"
  66. if not __gitnow_is_git_repository
  67. __gitnow_msg_not_valid_repository "untracked"
  68. return
  69. end
  70. command git clean --dry-run -d
  71. commandline -f repaint
  72. end
  73. function commit -d "Gitnow: Commit changes to the repository"
  74. if not __gitnow_is_git_repository
  75. __gitnow_msg_not_valid_repository "commit"
  76. return
  77. end
  78. set -l len (count $argv)
  79. if test $len -gt 0
  80. command git commit $argv
  81. else
  82. command git commit
  83. end
  84. commandline -f repaint
  85. end
  86. function commit-all -d "Gitnow: Add and commit all changes to the repository"
  87. if not __gitnow_is_git_repository
  88. __gitnow_msg_not_valid_repository "commit-all"
  89. return
  90. end
  91. stage
  92. commit .
  93. end
  94. function pull -d "Gitnow: Pull changes from remote server but stashing uncommitted changes"
  95. if not __gitnow_is_git_repository
  96. __gitnow_msg_not_valid_repository "pull"
  97. return
  98. end
  99. set -l len (count $argv)
  100. set -l xorigin (__gitnow_current_remote)
  101. set -l xbranch (__gitnow_current_branch_name)
  102. set -l xcmd ""
  103. echo "⚡️ Pulling changes..."
  104. set -l xdefaults --rebase --autostash --tags
  105. if test $len -gt 2
  106. set xcmd $argv
  107. echo "Mode: Manual"
  108. echo "Default flags: $xdefaults"
  109. echo
  110. else
  111. echo "Mode: Auto"
  112. echo "Default flags: $xdefaults"
  113. if test $len -eq 1
  114. set xbranch $argv[1]
  115. end
  116. if test $len -eq 2
  117. set xorigin $argv[1]
  118. set xbranch $argv[2]
  119. end
  120. set xcmd $xorigin $xbranch
  121. set -l xremote_url (command git config --get "remote.$xorigin.url")
  122. echo "Remote URL: $xorigin ($xremote_url)"
  123. echo "Remote branch: $xbranch"
  124. echo
  125. end
  126. command git pull $xcmd $xdefaults
  127. commandline -f repaint
  128. end
  129. # Git push with --set-upstream
  130. # Shortcut inspired from https://github.com/jamiew/git-friendly
  131. function push -d "Gitnow: Push commit changes to remote repository"
  132. if not __gitnow_is_git_repository
  133. __gitnow_msg_not_valid_repository "push"
  134. return
  135. end
  136. set -l opts $argv
  137. set -l xorigin (__gitnow_current_remote)
  138. set -l xbranch (__gitnow_current_branch_name)
  139. if test (count $opts) -eq 0
  140. set opts $xorigin $xbranch
  141. set -l xremote_url (command git config --get "remote.$xorigin.url")
  142. echo "🚀 Pushing changes..."
  143. echo "Mode: Auto"
  144. echo "Remote URL: $xorigin ($xremote_url)"
  145. echo "Remote branch: $xbranch"
  146. else
  147. set -l v_mode "auto"
  148. for v in $argv
  149. switch $v
  150. case -t --tags
  151. set opts $xorigin $xbranch --follow-tags
  152. set -l xremote_url (command git config --get "remote.$xorigin.url")
  153. echo "🚀 Pushing changes..."
  154. echo "Mode: Auto (incl. tags)"
  155. echo "Remote URL: $xorigin ($xremote_url)"
  156. echo "Remote branch: $xbranch"
  157. case -h --help
  158. echo "NAME"
  159. echo " Gitnow: push - Push current branch to default origin"
  160. echo "OPTIONS:"
  161. echo " -t --tags (auto mode) include annotated tags that relate to the commits"
  162. echo " -h --help Show information about the options for this command"
  163. return
  164. case -\*
  165. case '*'
  166. set -l v_mode "manual"
  167. echo "Mode: Manual"
  168. end
  169. end
  170. end
  171. echo
  172. command git push --set-upstream $opts
  173. commandline -f repaint
  174. end
  175. function upstream -d "Gitnow: Commit all changes and push them to remote server"
  176. if not __gitnow_is_git_repository
  177. __gitnow_msg_not_valid_repository "upstream"
  178. return
  179. end
  180. commit-all
  181. push
  182. end
  183. function feature -d "GitNow: Creates a new Gitflow feature branch from current branch" -a xbranch
  184. if not __gitnow_is_git_repository
  185. __gitnow_msg_not_valid_repository "feature"
  186. return
  187. end
  188. __gitnow_gitflow_branch "feature" $xbranch
  189. commandline -f repaint
  190. end
  191. function hotfix -d "GitNow: Creates a new Gitflow hotfix branch from current branch" -a xbranch
  192. if not __gitnow_is_git_repository
  193. __gitnow_msg_not_valid_repository "hotfix"
  194. return
  195. end
  196. __gitnow_gitflow_branch "hotfix" $xbranch
  197. commandline -f repaint
  198. end
  199. function bugfix -d "GitNow: Creates a new Gitflow bugfix branch from current branch" -a xbranch
  200. if not __gitnow_is_git_repository
  201. __gitnow_msg_not_valid_repository "bugfix"
  202. return
  203. end
  204. __gitnow_gitflow_branch "bugfix" $xbranch
  205. commandline -f repaint
  206. end
  207. function release -d "GitNow: Creates a new Gitflow release branch from current branch" -a xbranch
  208. if not __gitnow_is_git_repository
  209. __gitnow_msg_not_valid_repository "release"
  210. return
  211. end
  212. __gitnow_gitflow_branch "release" $xbranch
  213. commandline -f repaint
  214. end
  215. function merge -d "GitNow: Merges given branch into the active one"
  216. if not __gitnow_is_git_repository
  217. __gitnow_msg_not_valid_repository "merge"
  218. return
  219. end
  220. set -l len (count $argv)
  221. if test $len -eq 0
  222. echo "Merge: No argument given, needs one parameter"
  223. return
  224. end
  225. set -l v_abort
  226. set -l v_continue
  227. set -l v_branch
  228. for v in $argv
  229. switch $v
  230. case -a --abort
  231. set v_abort $v
  232. case -c --continue
  233. set v_continue $v
  234. case -h --help
  235. echo "NAME"
  236. echo " Gitnow: merge - Merge given branch into the active one"
  237. echo "EXAMPLES"
  238. echo " merge <branch to merge>"
  239. echo "OPTIONS:"
  240. echo " -a --abort Abort a conflicted merge"
  241. echo " -c --continue Continue a conflicted merge"
  242. echo " -h --help Show information about the options for this command"
  243. return
  244. case -\*
  245. case '*'
  246. set v_branch $v
  247. end
  248. end
  249. # abort
  250. if test "$v_abort";
  251. echo "Abort the current merge"
  252. command git merge --abort
  253. commandline -f repaint
  254. return
  255. end
  256. # continue
  257. if test "$v_continue";
  258. echo "Continue the current merge"
  259. command git merge --continue
  260. commandline -f repaint
  261. return
  262. end
  263. # No branch defined
  264. if not test -n "$v_branch"
  265. echo "Provide a valid branch name to merge."
  266. commandline -f repaint
  267. return
  268. end
  269. set -l v_found (__gitnow_check_if_branch_exist $v_branch)
  270. # Branch was not found
  271. if test $v_found -eq 0;
  272. echo "Local branch `$v_branch` was not found. Not possible to merge."
  273. commandline -f repaint
  274. return
  275. end
  276. # Detect merging current branch
  277. if [ "$v_branch" = (__gitnow_current_branch_name) ]
  278. echo "Branch `$v_branch` is the same as current branch. Nothing to do."
  279. commandline -f repaint
  280. return
  281. end
  282. command git merge $v_branch
  283. commandline -f repaint
  284. end
  285. function move -d "GitNow: Switch from current branch to another but stashing uncommitted changes"
  286. if not __gitnow_is_git_repository
  287. __gitnow_msg_not_valid_repository "move"
  288. return
  289. end
  290. set -l v_upstream
  291. set -l v_no_apply_stash
  292. set -l v_branch
  293. for v in $argv
  294. switch $v
  295. case -u --upstream
  296. set v_upstream $v
  297. case -n --no-apply-stash
  298. set v_no_apply_stash $v
  299. case -nu -un
  300. set v_upstream "-u"
  301. set v_no_apply_stash "-n"
  302. case -h --help
  303. echo "NAME"
  304. echo " Gitnow: move - Switch from current branch to another but stashing uncommitted changes"
  305. echo "EXAMPLES"
  306. echo " move <branch to switch to>"
  307. echo "OPTIONS:"
  308. echo " -n --no-apply-stash Switch to a local branch but without applying current stash"
  309. echo " -u --upstream Fetch a remote branch and switch to it applying current stash. It can be combined with --no-apply-stash"
  310. echo " -h --help Show information about the options for this command"
  311. return
  312. case -\*
  313. case '*'
  314. set v_branch $v
  315. end
  316. end
  317. # No branch defined
  318. if not test -n "$v_branch"
  319. echo "Provide a valid branch name to switch to."
  320. commandline -f repaint
  321. return
  322. end
  323. set -l v_fetched 0
  324. # Fetch branch from remote
  325. if test -n "$v_upstream"
  326. set -l v_remote (__gitnow_current_remote)
  327. command git fetch $v_remote $v_branch:refs/remotes/$v_remote/$v_branch
  328. command git checkout --track $v_remote/$v_branch
  329. commandline -f repaint
  330. return
  331. end
  332. set -l v_found (__gitnow_check_if_branch_exist $v_branch)
  333. # Branch was not found
  334. if begin test $v_found -eq 0; and test $v_fetched -eq 0; end
  335. echo "Branch `$v_branch` was not found locally. No possible to switch."
  336. echo "Tip: Use -u (--upstream) flag to fetch a remote branch."
  337. commandline -f repaint
  338. return
  339. end
  340. # Prevent same branch switching
  341. if [ "$v_branch" = (__gitnow_current_branch_name) ]
  342. echo "Branch `$v_branch` is the same as current branch. Nothing to do."
  343. commandline -f repaint
  344. return
  345. end
  346. set -l v_uncommited (__gitnow_has_uncommited_changes)
  347. # Stash changes before checkout for uncommited changes only
  348. if test $v_uncommited
  349. command git stash
  350. end
  351. command git checkout $v_branch
  352. # --no-apply-stash
  353. if test -n "$v_no_apply_stash"
  354. echo "Stashed changes were not applied. Use `git stash pop` to apply them."
  355. end
  356. if begin test $v_uncommited; and not test -n "$v_no_apply_stash"; end
  357. command git stash pop
  358. echo "Stashed changes applied."
  359. end
  360. commandline -f repaint
  361. end
  362. function logs -d "Gitnow: Shows logs in a fancy way"
  363. if not __gitnow_is_git_repository
  364. __gitnow_msg_not_valid_repository "logs"
  365. return
  366. end
  367. set -l v_max_commits "80"
  368. set -l v_args
  369. for v in $argv
  370. switch $v
  371. case -h --help
  372. echo "NAME"
  373. echo " Gitnow: logs - Show logs in a fancy way (first $v_max_commits commits by default)"
  374. echo "EXAMPLES"
  375. echo " logs [git log options]"
  376. echo "EXTRA OPTIONS:"
  377. echo " -h, --help Show information about the options for this command"
  378. return
  379. case -\*
  380. case '*'
  381. set v_args $argv
  382. break
  383. end
  384. end
  385. if test -n "$v_args"
  386. set v_max_commits
  387. else
  388. set v_max_commits "-$v_max_commits"
  389. end
  390. LC_ALL=C command git log $v_max_commits $v_args --color --graph \
  391. --pretty=format:"%C(red)%h%C(reset)%C(yellow)%d%Creset %s %C(green italic)(%cr)%C(reset) %C(blue)%an%C(reset) %C(white dim)%GK %C(reset)" --abbrev-commit \
  392. | command less -R
  393. end
  394. function tag -d "Gitnow: Tag commits following Semver"
  395. if not __gitnow_is_git_repository
  396. __gitnow_msg_not_valid_repository "tag"
  397. return
  398. end
  399. set -l v_major
  400. set -l v_minor
  401. set -l v_patch
  402. set -l v_premajor
  403. set -l v_preminor
  404. set -l v_prepatch
  405. set -l opts
  406. # NOTE: this function only gets the latest *Semver release version* but no suffixed ones or others
  407. set -l v_latest (__gitnow_get_latest_semver_release_tag)
  408. for v in $argv
  409. switch $v
  410. case -x --major
  411. set v_major $v
  412. case -y --minor
  413. set v_minor $v
  414. case -z --patch
  415. set v_patch $v
  416. case -a --annotate
  417. set opts $opts $v
  418. # TODO: pre-release versions are not supported yet
  419. # case -a --premajor
  420. # set v_premajor $v
  421. # case -b --preminor
  422. # set v_preminor $v
  423. # case -c --prepatch
  424. # set v_prepatch $v
  425. case -l --latest
  426. if not test -n "$v_latest"
  427. echo "There is no any tag created yet."
  428. else
  429. echo $v_latest
  430. end
  431. return
  432. case -h --help
  433. echo "NAME"
  434. echo " Gitnow: tag - List or tag commits following The Semantic Versioning 2.0.0 (Semver) [1]"
  435. echo " [1] https://semver.org/"
  436. echo "EXAMPLES"
  437. echo " List tags: tag"
  438. echo " Custom tag: tag <my tag name>"
  439. echo " Semver tag: tag --major"
  440. echo "OPTIONS:"
  441. echo " Without options all tags are listed in a lexicographic order and tag names are treated as versions"
  442. echo " -x --major Tag auto-incrementing a major version number"
  443. echo " -y --minor Tag auto-incrementing a minor version number"
  444. echo " -z --patch Tag auto-incrementing a patch version number"
  445. echo " -l --latest Show only the latest Semver release tag version (no suffixed ones or others)"
  446. echo " -a --annotate Create as annotated tag"
  447. echo " -h --help Show information about the options for this command"
  448. # TODO: pre-release versions are not supported yet
  449. # echo " -a --premajor Tag auto-incrementing a premajor version number"
  450. # echo " -b --preminor Tag auto-incrementing a preminor version number"
  451. # echo " -c --prepatch Tag auto-incrementing a prepatch version number"
  452. return
  453. case -\*
  454. case '*'
  455. return
  456. end
  457. end
  458. # List all tags in a lexicographic order and treating tag names as versions
  459. if test -z "$argv"
  460. __gitnow_get_tags_ordered
  461. return
  462. end
  463. # Major version tags
  464. if test -n "$v_major"
  465. if not test -n "$v_latest"
  466. command git tag $opts v1.0.0
  467. echo "First major tag \"v1.0.0\" was created."
  468. return
  469. else
  470. set -l vstr (__gitnow_get_valid_semver_release_value $v_latest)
  471. # Validate Semver format before to proceed
  472. if not test -n "$vstr"
  473. echo "The latest tag \"$v_latest\" has no a valid Semver format."
  474. return
  475. end
  476. set -l x (echo $vstr | LC_ALL=C command awk -F '.' '{print $1}')
  477. set -l prefix (echo $v_latest | LC_ALL=C command awk -F "$vstr" '{print $1}')
  478. set x (__gitnow_increment_number $x)
  479. set -l xyz "$prefix$x.0.0"
  480. command git tag $opts $xyz
  481. echo "Major tag \"$xyz\" was created."
  482. return
  483. end
  484. end
  485. # Minor version tags
  486. if test -n "$v_minor"
  487. if not test -n "$v_latest"
  488. command git tag $opts v0.1.0
  489. echo "First minor tag \"v0.1.0\" was created."
  490. return
  491. else
  492. set -l vstr (__gitnow_get_valid_semver_release_value $v_latest)
  493. # Validate Semver format before to proceed
  494. if not test -n "$vstr"
  495. echo "The latest tag \"$v_latest\" has no a valid Semver format."
  496. return
  497. end
  498. set -l x (echo $vstr | LC_ALL=C command awk -F '.' '{print $1}')
  499. set -l y (echo $vstr | LC_ALL=C command awk -F '.' '{print $2}')
  500. set -l prefix (echo $v_latest | LC_ALL=C command awk -F "$vstr" '{print $1}')
  501. set y (__gitnow_increment_number $y)
  502. set -l xyz "$prefix$x.$y.0"
  503. command git tag $opts $xyz
  504. echo "Minor tag \"$xyz\" was created."
  505. return
  506. end
  507. end
  508. # Patch version tags
  509. if test -n "$v_patch"
  510. if not test -n "$v_latest"
  511. command git tag $opts v0.0.1
  512. echo "First patch tag \"v0.1.0\" was created."
  513. return
  514. else
  515. set -l vstr (__gitnow_get_valid_semver_release_value $v_latest)
  516. # Validate Semver format before to proceed
  517. if not test -n "$vstr"
  518. echo "The latest tag \"$v_latest\" has no a valid Semver format."
  519. return
  520. end
  521. set -l x (echo $vstr | LC_ALL=C command awk -F '.' '{print $1}')
  522. set -l y (echo $vstr | LC_ALL=C command awk -F '.' '{print $2}')
  523. set -l z (echo $vstr | LC_ALL=C command awk -F '.' '{print $3}')
  524. set -l s (echo $z | LC_ALL=C command awk -F '-' '{print $1}')
  525. if __gitnow_is_number $s
  526. set -l prefix (echo $v_latest | LC_ALL=C command awk -F "$vstr" '{print $1}')
  527. set s (__gitnow_increment_number $s)
  528. set -l xyz "$prefix$x.$y.$s"
  529. command git tag $opts $xyz
  530. echo "Patch tag \"$xyz\" was created."
  531. else
  532. echo "No patch version found."
  533. end
  534. return
  535. end
  536. end
  537. # TODO: pre-release versions are not supported yet
  538. # TODO: Premajor version tags
  539. # TODO: Preminor version tags
  540. # TODO: Prepatch version tags
  541. commandline -f repaint
  542. end
  543. function assume -d "Gitnow: Ignore files temporarily"
  544. if not __gitnow_is_git_repository
  545. __gitnow_msg_not_valid_repository "assume"
  546. return
  547. end
  548. set -l v_assume_unchanged "--assume-unchanged"
  549. set -l v_files
  550. for v in $argv
  551. switch $v
  552. case -n --no-assume
  553. set v_assume_unchanged "--no-assume-unchanged"
  554. case -h --help
  555. echo "NAME"
  556. echo " Gitnow: assume - Ignores changes in certain files temporarily"
  557. echo "OPTIONS:"
  558. echo " -n --no-assume No assume unchanged files to be ignored (revert option)"
  559. echo " -h --help Show information about the options for this command"
  560. return
  561. case -\*
  562. case '*'
  563. set v_files $v_files $v
  564. end
  565. end
  566. if test (count $v_files) -lt 1
  567. echo "Provide files in order to ignore them temporarily. E.g `assume Cargo.lock`"
  568. return
  569. end
  570. command git update-index $v_assume_unchanged $v_files
  571. end
  572. function github -d "Gitnow: Clone a GitHub repository using SSH"
  573. set -l repo (__gitnow_clone_params $argv)
  574. __gitnow_clone_repo $repo "github"
  575. commandline -f repaint
  576. end
  577. function bitbucket -d "Gitnow: Clone a Bitbucket Cloud repository using SSH"
  578. set -l repo (__gitnow_clone_params $argv)
  579. __gitnow_clone_repo $repo "bitbucket"
  580. commandline -f repaint
  581. end