-
Notifications
You must be signed in to change notification settings - Fork 448
Feature: Add functionality to discard changes #356
Description
Discarding changes
Problem
When there are changes to files that the user isn't interested in keeping, they need a way of throwing away these changes. This is normally implemented via a Discard action for a specific file, or for all files.
Git overview
Git provides a checkout command that changes the working directory back to a previous state. This command can take:
- a commit (usually a branch name) - updates the working directory to the state of that commit
- a filename or list of files - updates the named files to the state of the commit (the current HEAD if no commit is specified)
git checkout [file] or git checkout -- [files], will only operate on files that are already tracked by git and will not work for new files. Also, if a file has already been added to the staging area, checkout [file] will not affect the changes in the staging area, it will only affect changes that have not been staged yet.
In this situation above, in order to discard changes to the different files, we need to do:
- README.me:
git checkout HEAD -- README.md - package.sh:
git checkout -- package.sh(git checkout HEAD -- package.shalso works) - a:
git checkoutwon't work, we need to manually delete the file.
git clean -f throws away new files / changes to untracked files, but won't reset tracked file changes back to what they were.
git reset --hard throws away all changes to tracked files but doesn't touch untracked (new) files
Solution
Technical backend - git operations
Discard changes to a single file
To implement "Discard changes to a particular file", we should:
- Check whether the file is new
- If yes, delete it
- If no,
git checkout HEAD -- [file]
Discard changes to all files
To implement "Discard all changes", there's several alternatives:
- clean and reset
- Run
git clean -fto throw away all new (untracked) files - Run
git reset --hardto reset all changed (tracked) files back to unchanged
- checkout and delete
- Categorize all files by new/existing (untracked/tracked)
- Delete all new (untracked) files
- Run
git checkout HEAD -- [files]on all existing (tracked) changed files
UI/UX
TBD
API technical details
Given that both discard and discard all requires at least two separate actions (as talked about in #356), that should probably be implemented in RepositoryManager. What we then need is:
RepositoryManager.cs (pseudocode):
DiscardAll():
GitClient.CleanUntrackedFiles()
GitClient.Checkout("HEAD")
DiscardFiles(List<GitFile> files):
where file in files.Added: Delete File via System.IO calls
all other files: GitClient.Checkout("HEAD", files)
We already have GitSwitchBranchesTask which basically does a git checkout. We should probably rename that one to GitCheckout and add an optional files parameter to it, calling either git checkout [branch] or git checkout [branch] -- files depending on whether there's a list of files to checkout. Checking out a branch is the same as checking out HEAD, there's no difference there
old issue body below
To implement a discard changes function in the user interface we first need to add the functionality to our api.
- Create
GitCheckoutTask,
a. The goal of this task is to rungit checkout.- It should be able to checkout on a specific file
git checkout path/to/file/to/revert - It should be able to checkout all files
git checkout -- .
b. You can useGitAddTaskas an example.
https://github.com/github-for-unity/Unity/blob/master/src/GitHub.Api/Git/Tasks/GitAddTask.cs
- It should be able to checkout on a specific file
- Add the functionality to use
GitCheckoutTasktoGitClient
a. Create aDiscardandDiscardAllmethod
b. You can use the methodsAddandAddAllas an example
https://github.com/github-for-unity/Unity/blob/master/src/GitHub.Api/Git/GitClient.cs#L371-393 - Add some integration tests
https://github.com/github-for-unity/Unity/blob/master/src/tests/IntegrationTests/Events/RepositoryManagerTests.cs
a. We need some integration tests to prove what you did is working correctly
b. You can use theShouldDetectFileChangestest as an example, it makes changes to the system and checks if they are there.
https://github.com/github-for-unity/Unity/blob/master/src/tests/IntegrationTests/Events/RepositoryManagerTests.cs#L24-L62
