Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-3851 improve 'amend' experience #4528

Closed
wants to merge 6 commits into from

Conversation

westbury
Copy link
Contributor

This PR improves the user experience when using the 'Amend' button.

  1. A list of the commits being amended is shown above the last commit.
  2. There is an 'Unamend' button that reverses the previous 'Amend'
  3. All commits being amended can be unamended using the '-' button in the section header
  4. The movement of commits in the 'last commit' section and the 'commits being amended' section are animated so that the user readily sees how commits are moving between the sections.

In the screenshot below you will see how the view looks after pressing 'Amend' twice.

amend

@westbury
Copy link
Contributor Author

@lmcbout I was wondering if this PR solves the UX issues you mentioned around the 'Amend' button.

This will need a bit of merging to work with #4279

@vince-fugnitto
Copy link
Member

@westbury I think the Amend section requires some form of minimum height to avoid the following:

Peek 2019-03-14 09-28

@lmcbout
Copy link
Contributor

lmcbout commented Mar 14, 2019

Hi @westbury
I am testing this current issue #3851 . I can see the section "Commits Being Amended", but the "Unamend" button shows on last commit only. This is OK , but when I reached the last "Commit" to "Unamend, I only see a little box that I cannot read, so unable to access the "Unamend" button .

To test, I select the "Amend" button a few times until the list of files was filling the height of the window view. When the number of files fill the height, we come to a point I don't see the section "COMMITS BEING AMENDED". The section becomes too small, there is no minimum height being kept to see it on the view. Then to select the "Unamend" button is not visible.

I think this functionality is very good since it allows the end-user to reset to the previous commit

@@ -343,9 +405,9 @@
cursor: pointer;
}

.git-theia-header:hover > .git-change-list-buttons-container {
.git-theia-header:hover>.git-change-list-buttons-container {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, but I'm not sure the removal of the spacing here is required.
Throughout Theia, we use this spacing in other css files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vince-fugnitto Thanks for looking at this. Yes, something looks very wrong there. I was aware it looked odd as the section got too small but I have not seen that. I will do further testing on Linux (I developed it on Windows).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of the space was unintentional and I did not notice it. I'll restore it.

@akosyakov akosyakov requested a review from svenefftinge March 14, 2019 14:29
@westbury
Copy link
Contributor Author

@lmcbout Thanks for trying it out. The 'Unamend' is only on the bottom commit because otherwise we are switching the order of commits with possible conflicts and other complications. I'll do some more tweaking of the UI to improve it when the sections need to shrink.

@svenefftinge
Copy link
Contributor

It looks pretty nice and improves the current state significantly. I wonder how we can keep this once we switch to the SCM + VS Code git extension. But I definitely would want to find a way.

@kittaakos Could you review as well?

@svenefftinge svenefftinge requested a review from kittaakos March 20, 2019 15:21
@kittaakos
Copy link
Contributor

I can see the following when trying to amend to the initial commit:

Uncaught (in promise) Error: Request 'exec' failed
    at Proxy.<anonymous> (bundle.js:98716)
    at GitWidget.<anonymous> (:3000/74.bundle.js:7034)
    at step (:3000/74.bundle.js:6712)
    at Object.next (:3000/74.bundle.js:6693)
    at fulfilled (:3000/74.bundle.js:6684)
08:27:53.578 :3000/74.bundle.js:6685 Uncaught (in promise) Error: Request 'exec' failed
    at Proxy.<anonymous> (bundle.js:98716)
    at GitWidget.<anonymous> (:3000/74.bundle.js:7034)
    at step (:3000/74.bundle.js:6712)
    at Object.next (:3000/74.bundle.js:6693)
    at fulfilled (:3000/74.bundle.js:6684)
08:27:59.595 git-widget.tsx:15 Uncaught (in promise) Error: Request 'exec' failed
    at Proxy.<anonymous> (proxy-factory.ts:232)
    at GitWidget.<anonymous> (git-widget.tsx:277)
    at step (git-widget.tsx:15)
    at Object.next (git-widget.tsx:15)
    at fulfilled (git-widget.tsx:15)

Perhaps the same issue exisits on the master as well.

@akosyakov
Copy link
Member

akosyakov commented Mar 21, 2019

My problem with this approach that it is not based on the single sourcing of git state, but keeps some in memory state. You can just open another page or reload page to see how it is confusing. We could build up shared state on the backend but it's rather complicate things.

Copy link
Contributor

@kittaakos kittaakos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 It works great, I have added a few remarks.

protected lastHead: string | undefined;
protected lastSelectedNode?: { id: number, node: GitFileChangeNode };
protected listContainer: GitChangesListContainer | undefined;
protected readonly selectChange = (change: GitFileChangeNode) => this.selectNode(change);

protected readonly toDisposeOnInitialize = new DisposableCollection();

protected lastCommitHeight: number = 100;
lastCommitScrollRef = (instance: HTMLDivElement) => {
if (instance && this.lastCommitHeight === 100) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the guard against instance? Can this be null or undefined?

packages/git/src/browser/git-widget.tsx Show resolved Hide resolved
packages/git/src/browser/git-widget.tsx Show resolved Hide resolved
case 'unamend':
const commitToRestore = this.amendingCommits.pop();
if (!nextCommit || !commitToRestore || nextCommit.commit.sha !== commitToRestore.commit.sha) {
// something is wrong
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If something is wrong please log it, or delete the if.


const { selectedRepository } = this.repositoryProvider;
if (selectedRepository && commitToRestore) {
const message = oldestAmendCommit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is very similar to the amend logic, can we extract and reuse it? If we ever hit a bug, we can fix it one place ;)

<div className={GitWidget.Styles.LAST_COMMIT_CONTAINER}>
<div id='lastCommit' className='changesContainer'>
<div className='theia-header git-theia-header'>
Head Commit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have HEAD Commit? What do you think?

{this.renderCommitCount(this.amendingCommits.length)}
{this.renderAmendCommitListButtons()}
</div>
{this.amendingCommits.map((commitData, index, map) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[minor]: map -> array (or commits)?

@kittaakos
Copy link
Contributor

trying to amend to the initial commit:

And here is the corresponding log from the backend:

root ERROR The command `git reset HEAD~ --soft` exited with an unexpected code: 128. The caller should either handle this error, or expect that exit code.
root ERROR fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

root ERROR Request exec failed with error: fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
 GitError: fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

    at new GitError (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:81:28)
    at Object.<anonymous> (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:256:27)
    at step (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:50:23)
    at Object.next (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:31:53)
    at fulfilled (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:22:58)
    at <anonymous>
root ERROR Uncaught Exception:  GitError: fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

root ERROR GitError: fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

    at new GitError (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:81:28)
    at Object.<anonymous> (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:256:27)
    at step (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:50:23)
    at Object.next (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:31:53)
    at fulfilled (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:22:58)
    at <anonymous>
root ERROR Uncaught Exception:  GitError: fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

root ERROR GitError: fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

    at new GitError (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:81:28)
    at Object.<anonymous> (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:256:27)
    at step (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:50:23)
    at Object.next (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:31:53)
    at fulfilled (/Users/akos.kitta/Desktop/theia/node_modules/dugite-extra/lib/core/git.js:22:58)
    at <anonymous>

Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
@westbury
Copy link
Contributor Author

My problem with this approach that it is not based on the single sourcing of git state, but keeps some in memory state. You can just open another page or reload page to see how it is confusing. We could build up shared state on the backend but it's rather complicate things.

Yes, I had thought of creating a special tag for the head of the amending commits, but the user may see the tag when using other tools and be confused by it. I think we can solve this simply using the storage service, and a key that contains the repository URI. The only thing we actually need to store is the SHA of the first amended commit. I'm working on this now.

Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
@westbury
Copy link
Contributor Author

I think the Amend section requires some form of minimum height to avoid the following

@vince-fugnitto I have re-written it to introduce a minimum height. This also changes the scroll bars so the commits being amended are now separately scrollable underneath the header for the amending commits.

@westbury
Copy link
Contributor Author

I wonder how we can keep this once we switch to the SCM + VS Code git extension. But I definitely would want to find a way.

@svenefftinge We want these changes and we also want the SCM + VS Code get extension, so we will definitely find a way. I had been waiting for #4279 before finalizing this PR but it looks like there is still quite a lot of work on that PR to get back to the same functionality.

Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
@westbury
Copy link
Contributor Author

I have now addressed all the code review comments and it is ready for reconsideration for merging.

@akosyakov I have made the changes to use the storage service to store the head of the list of commits being amended. This solves the issue of amend commits not showing after a refresh or opening another client instance. The changes are in a separate commit so can be reviewed separately 2bc1b45

@kittaakos I believe all your comments have been addressed. After the rewrite of the way transitions and scrolling were done, some comments were obsolete.

The git-widget file is getting big at 1365 lines. I'm sure it will get refactored a lot when/if it is merged into #4279 so I have not worried about the size and complexity for now.

@kittaakos
Copy link
Contributor

@kittaakos I believe all your comments have been addressed. After the rewrite of the way transitions and scrolling were done, some comments were obsolete.

👍 Thank you, @westbury! I am a bit busy with something else now, but the review will be done by the end of this week.

@kittaakos kittaakos self-requested a review April 25, 2019 14:20
@kittaakos
Copy link
Contributor

This solves the issue of amend commits not showing after a refresh or opening another client instance.

If I do a git reset --hard from the terminal, the view will be stuck in an inconsistent state which is OKish; it happens with VS Code too on a daily bases. However, when in VS Code, I Refresh the widget, it gets back to sync with the git status. It's not the case in Theia.

Screen Shot 2019-04-26 at 09 35 09

@kittaakos
Copy link
Contributor

Refreshing the browser does not help either. Would it be possible to add some logic that checks the git status state? If the git status is "empty", can we forcefully discard the amend state in the view?

@westbury
Copy link
Contributor Author

@kittaakos thanks for testing it. What I would expect is that making changes to the index or working tree will not affect the 'unamend'. So if one amends a commit, does a reset hard, and then unamends the commit, I would expect the commit to be restored and the working tree containing the reversion of the commit. The amend list is cleared only if HEAD changes. I have not tested the 'reset hard' case and will do that shortly.

@westbury
Copy link
Contributor Author

@kittaakos I've re-tested it and it is working as I expect. Changing the index or the working tree does not affect the list of amending commits. If one edits files, stages or unstages changes, or use any other way of changing the index or working tree such as 'git reset HEAD --hard', the list of amending commits remains and one can still restore commits. This is as I would expect. Changing the head, however, does clear the list. For example, committing some changes or git reset to something other than HEAD does clear the list.

It is a concern that this caused confusion as if it caused confusion to you it is sure to cause confusion to others. I have added another button to the 'Commits Being Amended' header that clears the list. This gives users a way of clearing the list after they find a refresh does not achieve that. Of course, doing a refresh should not be necessary to clear any 'problem'.

I'm not convinced that the amend list should be cleared simply because the index and working tree are clean. That just does not seem the right trigger for clearing the list. It is still valid to unamend a commit when clean.

Signed-off-by: Nigel Westbury <nigelipse@miegel.org>
@akosyakov
Copy link
Member

akosyakov commented Apr 29, 2019

I would prefer if we focus on testing and landing #4279 instead of adding more changes to git extension, after that we can add more functionality with a new approach. Otherwise it is only more deviations and adds mode burden on @vinokurig. cc @svenefftinge

@westbury
Copy link
Contributor Author

westbury commented Jun 1, 2019

The code in this PR was merged into #4279 which has now been merged to master. Therefore I am closing this PR.

@westbury westbury closed this Jun 1, 2019
@westbury westbury deleted the 3851-amend branch June 1, 2019 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants