-
Notifications
You must be signed in to change notification settings - Fork 446
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.sh
also works) - a:
git checkout
won'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 -f
to throw away all new (untracked) files - Run
git reset --hard
to 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 useGitAddTask
as 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
GitCheckoutTask
toGitClient
a. Create aDiscard
andDiscardAll
method
b. You can use the methodsAdd
andAddAll
as 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 theShouldDetectFileChanges
test 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