Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ProGit.pdf
Скачиваний:
7
Добавлен:
18.05.2015
Размер:
4.02 Mб
Скачать

Interactive Staging

Git comes with a couple of scripts that make some command-line tasks easier. Here, you’ll look at a few interactive commands that can help you easily craft your commits to include only certain combinations and parts of files. These tools are very helpful if you modify a bunch of files and then decide that you want those changes to be in several focused commits rather than one big messy commit. This way, you can make sure your commits are logically separate changesets and can be easily reviewed by the developers working with you. If you run git add with the -i or --interactive option, Git goes into an interactive shell mode, displaying something like this:

$ git add -i

 

 

 

 

 

staged unstaged path

 

1:

unchanged

+0/-1 TODO

 

2:

unchanged

+1/-1 index.html

3:

unchanged

+5/-1 lib/simplegit.rb

*** Commands ***

 

 

 

1: status

2: update

3: revert 4: add untracked

5: patch

6: diff

 

7: quit

8: help

What now>

 

 

 

 

You can see that this command shows you a much different view of your staging area — basically the same information

you get with git status but a bit more succinct and informative. It lists the changes you’ve staged on the left and unstaged changes on the right.

After this comes a Commands section. Here you can do a number of things, including staging files, unstaging files, staging parts of files, adding untracked files, and seeing diffs of what has been staged.

Staging and Unstaging Files

If you type 2 or u at the What now> prompt, the script prompts you for which files you want to stage:

What now> 2

 

 

staged

unstaged path

1:

unchanged

+0/-1 TODO

2:

unchanged

+1/-1 index.html

3:

unchanged

+5/-1 lib/simplegit.rb

Update>>

To stage the TODO and index.html files, you can type the numbers:

Update>> 1,2

 

 

staged unstaged path

* 1:

unchanged

+0/-1 TODO

* 2:

unchanged

+1/-1 index.html

3:

unchanged

+5/-1 lib/simplegit.rb

Update>>

The * next to each file means the file is selected to be staged. If you press Enter after typing nothing at the Update>> prompt, Git takes anything selected and stages it for you:

Update>> updated 2 paths

*** Commands ***

 

 

1: status

2: update

3: revert 4: add untracked

5: patch

6: diff

7: quit

8: help

What now> 1

staged unstaged path

1:+0/-1 nothing TODO

2:+1/-1 nothing index.html

3: unchanged +5/-1 lib/simplegit.rb

Now you can see that the TODO and index.html files are staged and the simplegit.rb file is still unstaged. If you want to unstage the TODO file at this point, you use the 3 or r (for revert) option:

*** Commands ***

 

 

1: status

2: update

3: revert 4: add untracked

5: patch

6: diff

7: quit

8: help

What now> 3

staged unstaged path

1:+0/-1 nothing TODO

2:+1/-1 nothing index.html

3:

unchanged

+5/-1 lib/simplegit.rb

Revert>> 1

 

 

staged

unstaged path

* 1:

+0/-1

nothing TODO

2:+1/-1 nothing index.html

3: unchanged

+5/-1 lib/simplegit.rb

Revert>> [enter]

 

reverted one path

 

Looking at your Git status again, you can see that you’ve unstaged the TODO file:

*** Commands ***

 

 

1: status

2: update 3: revert 4: add untracked

5: patch

6: diff

7: quit

8: help

What now> 1

 

 

staged unstaged path

 

1: unchanged

+0/-1 TODO

 

2:+1/-1 nothing index.html

3: unchanged +5/-1 lib/simplegit.rb

To see the diff of what you’ve staged, you can use the 6 or d (for diff) command. It shows you a list of your staged files,

and you can select the ones for which you would like to see the staged diff. This is much like specifying git diff --cached on the command line:

*** Commands ***

 

 

1: status

2: update

3: revert 4: add untracked

5: patch

6: diff

7: quit

8: help

What now> 6

 

 

 

 

staged

unstaged path

 

1:

+1/-1

nothing index.html

Review diff>> 1

 

 

 

diff --git a/index.html b/index.html

 

index 4d07108..4335f49 100644

--- a/index.html

+++ b/index.html

@@ -16,7 +16,7 @@ Date Finder

<p id="out">...</p>

-<div id="footer">contact : support@github.com</div>

+<div id="footer">contact : email.support@github.com</div>

<script type="text/javascript">

With these basic commands, you can use the interactive add mode to deal with your staging area a little more easily.

git add -p
git add --patch
git commit

Staging Patches

It’s also possible for Git to stage certain parts of files and not the rest. For example, if you make two changes to your simplegit.rb file and want to stage one of them and not the other, doing so is very easy in Git. From the interactive prompt, type 5 or p (for patch). Git will ask you which files you would like to partially stage; then, for each section of the selected files, it will display hunks of the file diff and ask if you would like to stage them, one by one:

diff --git a/lib/simplegit.rb b/lib/simplegit.rb index dd5ecc4..57399e0 100644

--- a/lib/simplegit.rb

+++ b/lib/simplegit.rb

@@ -22,7 +22,7 @@ class SimpleGit end

def log(treeish = 'master')

- command("git log -n 25 #{treeish}") + command("git log -n 30 #{treeish}")

end

def blame(path)

Stage this hunk [y,n,a,d,/,j,J,g,e,?]?

You have a lot of options at this point. Typing ? shows a list of what you can do:

Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ? y - stage this hunk

n - do not stage this hunk

a - stage this and all the remaining hunks in the file

d - do not stage this hunk nor any of the remaining hunks in the file g - select a hunk to go to

/ - search for a hunk matching the given regex

j - leave this hunk undecided, see next undecided hunk J - leave this hunk undecided, see next hunk

k - leave this hunk undecided, see previous undecided hunk K - leave this hunk undecided, see previous hunk

s - split the current hunk into smaller hunks e - manually edit the current hunk

? - print help

Generally, you’ll type y or n if you want to stage each hunk, but staging all of them in certain files or skipping a hunk decision until later can be helpful too. If you stage one part of the file and leave another part unstaged, your status output will look like this:

What now> 1

 

staged

unstaged path

1: unchanged

+0/-1 TODO

2:+1/-1 nothing index.html

3:+1/-1 +4/-0 lib/simplegit.rb

The status of the simplegit.rb file is interesting. It shows you that a couple of lines are staged and a couple are unstaged. You’ve partially staged this file. At this point, you can exit the interactive adding script and run to commit the partially staged files.

Finally, you don’t need to be in interactive add mode to do the partial-file staging — you can start the same script by using

or on the command line.

git stash list
git stash

Stashing

Often, when you’ve been working on part of your project, things are in a messy state and you want to switch branches for a bit to work on something else. The problem is, you don’t want to do a commit of half-done work just so you can get back to this point later. The answer to this issue is the command.

Stashing takes the dirty state of your working directory — that is, your modified tracked files and staged changes — and saves it on a stack of unfinished changes that you can reapply at any time.

Stashing Your Work

To demonstrate, you’ll go into your project and start working on a couple of files and possibly stage one of the changes. If you run git status , you can see your dirty state:

$ git status

#On branch master

#Changes to be committed:

#(use "git reset HEAD <file>..." to unstage)

#modified: index.html

#

#Changes not staged for commit:

#(use "git add <file>..." to update what will be committed)

#modified: lib/simplegit.rb

#

Now you want to switch branches, but you don’t want to commit what you’ve been working on yet; so you’ll stash the changes. To push a new stash onto your stack, run git stash :

$ git stash

Saved working directory and index state \

"WIP on master: 049d078 added the index file" HEAD is now at 049d078 added the index file (To restore them type "git stash apply")

Your working directory is clean:

$ git status

# On branch master

nothing to commit (working directory clean)

At this point, you can easily switch branches and do work elsewhere; your changes are stored on your stack. To see which stashes you’ve stored, you can use :

$ git stash list

stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051... Revert "added file_size" stash@{2}: WIP on master: 21d80a5... added number to log

In this case, two stashes were done previously, so you have access to three different stashed works. You can reapply the one you just stashed by using the command shown in the help output of the original stash command: git stash apply . If you want to apply one of the older stashes, you can specify it by naming it, like this: git stash apply stash@{2} . If you don’t specify a stash, Git assumes the most recent stash and tries to apply it:

git stash drop

$ git stash apply

#On branch master

#Changes not staged for commit:

#(use "git add <file>..." to update what will be committed)

#modified: index.html

#modified: lib/simplegit.rb

#

You can see that Git re-modifies the files you uncommitted when you saved the stash. In this case, you had a clean working directory when you tried to apply the stash, and you tried to apply it on the same branch you saved it from; but having a clean working directory and applying it on the same branch aren’t necessary to successfully apply a stash. You can save a stash on one branch, switch to another branch later, and try to reapply the changes. You can also have modified and uncommitted files in your working directory when you apply a stash — Git gives you merge conflicts if anything no longer applies cleanly.

The changes to your files were reapplied, but the file you staged before wasn’t restaged. To do that, you must run the git stash apply command with a --index option to tell the command to try to reapply the staged changes. If you had run that instead, you’d have gotten back to your original position:

$ git stash apply --index

#On branch master

#Changes to be committed:

#(use "git reset HEAD <file>..." to unstage)

#modified: index.html

#

#Changes not staged for commit:

#(use "git add <file>..." to update what will be committed)

#modified: lib/simplegit.rb

#

The apply option only tries to apply the stashed work — you continue to have it on your stack. To remove it, you can run with the name of the stash to remove:

$ git stash list

stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051... Revert "added file_size" stash@{2}: WIP on master: 21d80a5... added number to log

$ git stash drop stash@{0}

Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)

You can also run git stash pop to apply the stash and then immediately drop it from your stack.

Un-applying a Stash

In some use case scenarios you might want to apply stashed changes, do some work, but then un-apply those changes that originally came from the stash. Git does not provide such a stash unapply command, but it is possible to achieve the effect by simply retrieving the patch associated with a stash and applying it in reverse:

$ git stash show -p stash@{0} | git apply -R

Again, if you don’t specify a stash, Git assumes the most recent stash:

$ git stash show -p | git apply -R

You may want to create an alias and effectively add a stash-unapply command to your Git. For example:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R' $ git stash

$ #... work work work $ git stash-unapply

Creating a Branch from a Stash

If you stash some work, leave it there for a while, and continue on the branch from which you stashed the work, you may have a problem reapplying the work. If the apply tries to modify a file that you’ve since modified, you’ll get a merge conflict and will have to try to resolve it. If you want an easier way to test the stashed changes again, you can run git stash branch , which creates a new branch for you, checks out the commit you were on when you stashed your work, reapplies your work there, and then drops the stash if it applies successfully:

$ git stash branch testchanges Switched to a new branch "testchanges"

#On branch testchanges

#Changes to be committed:

#(use "git reset HEAD <file>..." to unstage)

#modified: index.html

#

#Changes not staged for commit:

#(use "git add <file>..." to update what will be committed)

#modified: lib/simplegit.rb

#

Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

This is a nice shortcut to recover stashed work easily and work on it in a new branch.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]