Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple staging areas

Tags:

git

Can I have multiple staging areas or achieve a similar effect using git?

My typical work flow is along the lines of:

  • work, work, work
  • now I have an idea of something useful, let's commit it git add -p, y, y
  • but first these smaller style changes: git reset HEAD .
  • git add -p, n, n, y, q, git commit -m "style changes"
  • git add -p .. commit the actual thing

Sometimes 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.

like image 317
Thomas Jensen Avatar asked Mar 09 '15 16:03

Thomas Jensen


People also ask

What does the staging area mean?

Definition of staging area : an area in which participants in a new especially military operation or mission are assembled and readied.

What is the difference between staging area and staging area group?

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.

What is a staging area in a warehouse?

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 a staging area in manufacturing?

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.


1 Answers

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.

like image 107
torek Avatar answered Sep 27 '22 21:09

torek