summaryrefslogtreecommitdiffstats
path: root/site/opinions/StackedGit2.org
blob: a4a2e3b64b8d53e64376a4b3119c8d8ec83874e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#+SERIES: index.html
#+SERIES_PREV: StackedGit.html

#+TITLE: How I Keep Using Stacked Git at ~$WORK~

One year ago, I have published an article summarizing
[[./StackedGit.html][my experience using Stacked Git at ~$WORK~]]. Twelve months later,
enough has changed to motivate a spin-off piece.

* Stacked Git is /Fast/
  Firstly, it is important to state that my main complain is now a
  thing of the past! In particular, Stacked Git does not feel slow
  anymore, and far from it. This is because
  [[https://github.com/stacked-git/stgit/discussions/185][Stacked Git 2.0 has been rewritten in Rust]]. RiiR (/Rewrite it in
  Rust/) is a running meme on the Internet, but in this particular
  case, the result is very exciting.

  Thanks to the performance boost, my Zsh prompt does not take 0.1s to
  appear.

  Speaking of Zsh prompt, basically what I ended up displaying is
  ~(<TOP PATCH NAME> <APPLIED PATCHES COUNT>/<PATCHSET SIZE> <HIDDEN
  PATCHES COUNT)~. For instance, ~(fix-1337 1/2 3)~.

  In case you want to take inspiration in my somewhat working
  configuration, here is the snippet of interest.

  #+begin_src sh
local series_top="$(stg top 2> /dev/null)"
local total="$(stg series 2> /dev/null | wc -l)"
local hidden="$(stg series --hidden 2> /dev/null | wc -l)"

if [[ "${total}" -gt 0 ]]; then
    local not_applied="$(stg series | grep -E '^-' | wc -l)"
    local applied="$(($total - $not_applied))"

    if [[ -z "${series_top}" ]]; then
        series_top="·"
    fi

    echo -n "(${status_color}${series_top} ${applied}/${total} ${hidden})"
    echo -n "  ($(current_branch))"
fi
  #+end_src

* Branchless Workflow
  Last year, I was using Stacked Git on top of git branches. More
  precisely, I had one branch for each (stack of) Merge Request. It
  worked well, because my typical MR counted 3 to 4 commits in
  average.

  [[mn:onecommit][This approach comes with its set of drawbacks too,
  it goes without saying. During the past year, I’ve pushed fairly
  large commits which could have been splitted into several smaller
  ones. I have also had to manage large stacks of MRs.]]

  Fast forward today, and things have changed on this front too. In a
  nutshell, I have become a “one commit per MR” maximalist of sort. I
  find this approach very effective to get more focused reviews, and
  to reduce the time it takes for a given MR to be integrated into the
  main branch. My previous approach did not scale well with this new
  mindset, and during the course of the year, I stopped using branches
  altogether.

  I did not invent the branchless workflow, of course.
  After it was first published, someone posted a link to my Stacked
  Git article on Hacker News, and
  [[https://news.ycombinator.com/item?id=29959224][*@arxanas* posted a comment about ~git-branchless~]]. I tried the
  tool, and even if it never clicked for me, I was really compelled by
  its core ideas. Similarly,
  [[https://drewdevault.com/2020/04/06/My-weird-branchless-git-workflow.html][Drew DeVault has published a complete article on its own branchless
  workflow in 2020]].

  In my case, I proceeds as follows.

  1. I name each patch after the branch to which I will push it on our
     upstream Git remote.
  3. I created a small git plugin I called ~git-prepare~ which allows
     me to select one of the patch of my current patchset using ~fzf~,
     and which pops all other patches that are currently applied.
  2. 99% of the time, I push my work using ~git push -f upstream @:$(stg top)~

  ~git-prepare~ is really straightforward:

  #+begin_src sh
#!/bin/sh
patch=$(stg series -P | fzf)

if [[ ! $? -eq 0 ]] ; then
    exit $?
fi

if [ -n "$(stg series -A)" ]; then
    stg pop -a
fi

stg push ${patch}
  #+end_src

  The main hurdle which I still need to figure out is how to deal with
  stacked MRs. Currently, this is very manual. I need to remember
  which commit belongs to the stack, the order and dependencies of
  these commits, and I need to publish each commit individually using
  ~stg push; git push @:$(stg top)~.

  The pragmatic answer is definitely to come back to git branches for
  this use case in particular, but it's not the /fun/ answer. So from
  time to time, I try to experiment new approaches. My current
  intuition is that, by adopting a naming convention for my patches, I
  could probably implement a thin tooling on top of Stacked Git to
  deal with dependents commits.

* Conclusion

  Putting aside stacked MRs for now, I am really satisfied with my
  workflow. It’s very lightweight and intuitive, and working without
  Stacked Git now feels backward and clunky.

  So I will take this opportunity to thank one more time Stacked Git’s
  authors and contributors. You all are making my professional like
  easier with your project.