Open uniquejava opened 6 years ago
!!!
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
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.
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
目标是用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
套路如下:
详细参考了这里的示例:
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