uniquejava / blog

My notes regarding the vibrating frontend :boom and the plain old java :rofl.
Creative Commons Zero v1.0 Universal
11 stars 5 forks source link

JGit #207

Open uniquejava opened 6 years ago

uniquejava commented 6 years ago

目标是用jgit实现我所知道的所有git命令行操作: 见: https://github.com/uniquejava/blog/issues/16

快速上手

Getting Started with JGit

GitDir和WorkTree分离

https://git-scm.com/book/en/v2/Appendix-B%3A-Embedding-Git-in-your-Applications-JGit

根据commitId得到commit时间

根据tag找到objectid再找到revCommit最后得到time https://stackoverflow.com/questions/25755475/how-to-obtain-the-revcommit-or-objectid-from-a-sha1-id-string-with-jgit

git log:

https://stackoverflow.com/questions/31060706/jgit-using-parameters-with-logcommand

git rebase:

先认真读一遍: Git Tools - Rewriting History

然后参见这里: https://stackoverflow.com/questions/22945257/jgit-how-to-squash-commits

套路如下:

InteractiveHandler handler = new InteractiveHandler() {
    public void prepareSteps(List<RebaseTodoLine> steps) {
        // loop through steps and use setAction to change action
    }

    public String modifyCommitMessage(String oldMessage) {
        return oldMessage;
    }
};

Repository repo = FileRepositoryBuilder.create(gitDir);
Git git = Git.wrap(repo);
git.rebase().setUpstream(commitA).runInteractively(handler).call();

详细参考了这里的示例: https://github.com/centic9/jgit-cookbook/blob/master/src/main/java/org/dstadler/jgit/porcelain/RebaseToOriginMaster.java

Git: “Cannot 'squash' without a previous commit” error while rebase

https://stackoverflow.com/questions/39595034/git-cannot-squash-without-a-previous-commit-error-while-rebase

uniquejava commented 6 years ago

git reflog

!!!

git rebase --onto \ \ \

I can't understand the behaviour of git rebase --onto 👍 git checkout B && git rebase A 等价于 git checkout B && git rebase --onto A B^

cyper实战 (我想删除v4) ~~~ 天拉(我其实是想squash v4, 不是想删除)

➜  gittest git:(master) git log --oneline|tee
5a8559c v5
8428660 v4
0e369b2 v3
898c677 add new file
3ab5de7 v2
e747958 v1
➜  gittest git:(master) git rebase --onto 0e369b2 8428660
First, rewinding head to replay your work on top of it...
Applying: v5
➜  gittest git:(master) git log --oneline|tee
4c799fe v5
0e369b2 v3
898c677 add new file
3ab5de7 v2
e747958 v1
➜  gittest git:(master)

这其实并不是我想要的. 我只是想squash v4

git merge --squash && HEAD@{1}

Squash my last X commits together using Git

You can use git merge --squash for this, which is slightly more elegant than git rebase -i. Suppose you're on master and you want to squash the last 12 commits into one. First check that git status is clean (since git reset --hard will throw away staged and unstaged changes) and then:

# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12

# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}

# Commit those squashed changes.  The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit

The documentation for git merge describes the --squash option in more detail.


Update: the only real advantage of this method over the simpler git reset --soft HEAD~12 && git commit suggested by Chris Johnsen in his answer is that you get the commit message prepopulated with every commit message that you're squashing.

uniquejava commented 6 years ago

jgit中的git add .

see How can I use JGit to add deleted files to the index?

我的最终代码如下:

public DirCache add(String... patterns) throws Exception {

    // setUpdate false to track all files specified in fileList
    // files added/modified
    AddCommand adder = git.add().setUpdate(false);
    for (String pattern : patterns) {
        adder.addFilepattern(pattern);
    }

    // if tracked files are deleted
    // see
    // https://stackoverflow.com/questions/32876426/how-can-i-use-jgit-to-add-deleted-files-to-the-index
    Status status = git.status().call();
    Set<String> missingFiles = status.getMissing();
    if (!missingFiles.isEmpty()) {
        logger.info("missing:");
        logger.info(StringUtils.join(missingFiles, ","));
        RmCommand rm = git.rm();
        for (String file : missingFiles) {
            rm.addFilepattern(file);
        }
        rm.call();
    }

    return adder.call();
}

下面是测试

➜  gittest git:(master) ✗ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    deleted:    a/b/add.txt
    modified:   a/b/xx.fdic.xml

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    a/b/newly_added.txt
    others
g.status();
// test add
g.add("a/b");
g.status();
g.commit("test add delete", false);

输出

[2018-05-25 15:13:20,632 INFO]missing: 
[2018-05-25 15:13:20,645 INFO]a/b/add.txt
[2018-05-25 15:13:20,646 INFO]added(index): 
[2018-05-25 15:13:20,646 INFO]
[2018-05-25 15:13:20,647 INFO]modified: 
[2018-05-25 15:13:20,647 INFO]a/b/xx.fdic.xml
[2018-05-25 15:13:20,647 INFO]changed(index): 
[2018-05-25 15:13:20,647 INFO]
[2018-05-25 15:13:20,648 INFO]uncommited(index): 
[2018-05-25 15:13:20,648 INFO]a/b/add.txt,a/b/xx.fdic.xml
[2018-05-25 15:13:20,648 INFO]removed(index): 

执行了新版的add

[2018-05-25 15:13:20,730 INFO]missing: 
[2018-05-25 15:13:20,730 INFO]
[2018-05-25 15:13:20,731 INFO]added(index): 
[2018-05-25 15:13:20,731 INFO]a/b/newly_added.txt
[2018-05-25 15:13:20,731 INFO]modified: 
[2018-05-25 15:13:20,731 INFO]
[2018-05-25 15:13:20,732 INFO]changed(index): 
[2018-05-25 15:13:20,732 INFO]a/b/xx.fdic.xml
[2018-05-25 15:13:20,732 INFO]uncommited(index): 
[2018-05-25 15:13:20,733 INFO]a/b/newly_added.txt,a/b/add.txt,a/b/xx.fdic.xml
[2018-05-25 15:13:20,733 INFO]removed(index): 
[2018-05-25 15:13:20,733 INFO]a/b/add.txt
uniquejava commented 6 years ago

git diff

How to show changes between commits with JGit

What’s the Difference? Creating Diffs with JGit