Can I have multiple staging areas or achieve a similar effect using git?
My typical work flow is along the lines of:
git add -p
, y
, y
git reset HEAD .
git add -p
, n
, n
, y
, q
, git commit -m "style changes"
git add -p
.. commit the actual thingSometimes I have 20 smaller commits to make from a huge pile of changes. It would save me hours a day, if I could run through the patches like git add -p
and then "dispatch" each patch to it's own staging area and commit each area separately.
Definition of staging area : an area in which participants in a new especially military operation or mission are assembled and readied.
The staging area group corresponds to a storage type (storage type role “D”), while the staging area corresponds to a storage section. You can divide each staging area into one or more storage bins. You need multiple storage bins, for example, if you want to define a loading sequence.
Staging areas are used for the interim storage of goods in the warehouse. They are located in close proximity to the doors assigned to them. You can define staging areas for different purposes and even simultaneously for multiple purposes: ● Goods receipt. Interim storage of unloaded goods until they are put away.
What is staging in manufacturing? Simply put, material staging is transferring the items needed from different work centers to the assembly location. Materials are staged for production at a certain time, in a particular quantity, and at a designated staging area.
Edit, 30 May 2020: In Git 2.15 or later I recommend using git worktree
instead of trying to do the below. There are some restrictions on added work-trees that make them somewhat annoying for this kind of work-flow, but it can work, and is built in to modern Git.
Note that if you do do something like I describe below, git gc
won't know to look in your alternate index files, and in fact, from its original introduction in Git 2.5 until it was fixed in Git 2.15, git gc
forgot to check added work-trees and their index files!
See VonC's answer for more.
You can in fact have multiple different staging areas (more literally, multiple index files) in git. To achieve the effect you want you would have to write your own variant of git add -p
anyway, so what I will do here is sketch an outline, as it were, of how to do this.
The default index file—the one git uses if you don't direct it to some other index file—lives in .git/index
(or, more shell-correctly, $GIT_DIR/.index
where $GIT_DIR
is taken from the environment or, if not set there, from git rev-parse --git-dir
).
If you set the environment variable GIT_INDEX_FILE
, however, git will use that file instead as the index. Thus, you might begin your "scatter changes to four branches" process by doing something like this:
GIT_DIR=${GIT_DIR:-$(git rev-parse --git-dir)} || exit 1 index_tmp_dir=$(mktemp -d) || exit 1 trap "rm -rf $index_tmp_dir" 0 1 2 3 15 # clean up on exit # make four copies of initial staging area for f in i1 i2 i3 i4; do cp $GIT_DIR/index $index_tmp_dir/$f done # THIS IS THE HARD PART: # Now, using `git diff-files -p` or similar, get patches # (diff hunks). # Whenever you're ready to stage one, pick an index for it, # then use: GIT_INDEX_FILE=$index_tmp_dir/$which git apply --cached < diffhunk # Once done, commit each index file separately with some # variation on: for f in i1 i2 i3 i4; do GIT_INDEX_FILE=$index_tmp_dir/$which git commit done
For the part labeled "hard part", your best bet might well be to copy git's add-interactive perl script, found in $(git --exec-path)/git-add--interactive
, then modify it to suit. To remove the "exactly four commits" restriction, make this modified interactive-add create a new index file dynamically (by copying the original, or perhaps creating an "empty" index equal to the HEAD
commit or whatever; see git read-tree
as well).
Edit: the some variation on section really should almost certainly use git write-tree
and git commit-tree
to make new branches out of each of these commits, using the parent of the current commit as their parent, rather than allowing git commit
to string the commits together as a linear chain. That means one must also choose some naming scheme for these various newly-created branches.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With