Another really handy thing with Git, which I do use regularly, is it's ability to split lots of changes to the same file into separate logical commits.
As far as I know, any of the other VCSs I've used in the past haven't supported this and the only sane way I know of doing so would be to copy the file away, and use vimdiff to copy the logical commits one-by-one, committing each in turn.
Thankfully, git makes this really easy with the git add command.
Set up an example repository
# Create a new git repository for this example cd /tmp/ mkdir git-add-pi cd git-add-pi/ git init # Make our first commit echo "Example line" > example-file git add example-file git commit -m "First part of the example file"
Make some changes to our example file
Make a change to the beginning of the file:
(echo "Some big sweeping change to the file"; cat example-file) > tmp; mv tmp example-fileand make a change to the end of the file:
echo "Another big sweeping change to the same file" >> example-file
The magic
We actually wanted to split that file into two logical commits. With subversion, that would be a pain, but with git it's really easy with git add --pi:
523 git-add-pi:master> git add -pi example-file diff --git a/example-file b/example-file index d503a0c..82d4c17 100644 --- a/example-file +++ b/example-file @@ -1 +1,3 @@ +Some big sweeping change to the file Example line +Another big sweeping change to the same file Stage this hunk [y/n/a/d/s/?]?
Because the lines are so close to one another, git hasn't automatically split them up. Specify s to split them:
Stage this hunk [y/n/a/d/s/?]? s Split into 2 hunks. @@ -1 +1,2 @@ +Some big sweeping change to the file Example line Stage this hunk [y/n/a/d/j/J/?]?Well, we want to commit this hunk, so hit y
Stage this hunk [y/n/a/d/j/J/?]? y @@ -1 +2,2 @@ Example line +Another big sweeping change to the same file Stage this hunk [y/n/a/d/K/?]? nWe didn't want this hunk as part of this logical commit, so choose n
Checking what we've done
We can double check what we've added so far:
524 git-add-pi:master> git diff --cached diff --git a/example-file b/example-file index d503a0c..8bca897 100644 --- a/example-file +++ b/example-file @@ -1 +1,2 @@ +Some big sweeping change to the file Example lineAnd commit as normal:
525 git-add-pi:master> git commit -m "First change" Created commit ad01f32: First change 1 files changed, 1 insertions(+), 0 deletions(-)
What about the rest of the file?
You can repeat the add -pi as much as you like, or since we only have one more line to commit:
526 git-add-pi:master> git add . git commi527 git-add-pi:master> git commit -m "final commit" Created commit 16722ed: final commit 1 files changed, 1 insertions(+), 0 deletions(-)
the "git gui" interface for this is really nice, letting you quickly stage and unstage things at the granularity of file, hunk or line
ReplyDelete